- Android启动时会运行com.android.bluetooth,后者一启动便会加载由<aosp>/system/bt编译出的BLE HAL模块libbluetooth.so。
- 针对ROC-RK3588S-PC,BLE HAL模块源码位在<aosp>/systrem/bt,没在<aosp>/hardward。

一、connectGatt“顶层”逻辑
要操作BLE设备,第一步就是要连接设备,其实就是连接BLE设备上的GATT service。这里结合源码,分析GATT连接流程,以及各个模块是怎么相互交互。
首先,一般应用层都是通过调用如下方法,来创建一个 GATT 连接。
mBluetoothGatt = device.connectGatt(this, false, mGattCallback, TRANSPORT_LE);
这里调用了方法connectGatt(),我们来看一下源码。
<aosp>/frameworks/base/core/java/android/bluetooth/BluetoothDevice.java
------
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback, int transport,
boolean opportunistic, int phy, Handler handler) {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
// managerService是Binder代理对象,它对应的本地对象是个叫BLUETOOTH_MANAGER_SERVICE("bluetooth_manager")的Binder组件,
// 整系统只有一个,即所有app共用一个BluetoothAdapter本地对象。
IBluetoothManager managerService = adapter.getBluetoothManager();
try {
IBluetoothGatt iGatt = managerService.getBluetoothGatt();
if (iGatt == null) {
// BLE is not supported
return null;
}
// 创建一个 BluetoothGatt 对象
BluetoothGatt gatt = new BluetoothGatt(
iGatt, this, transport, opportunistic, phy, mAttributionSource);
// 发起连接
gatt.connect(autoConnect, callback, handler);
return gatt;
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
return null;
}这里通过BluetoothAdapter获取managerService,这是通过Binder机制获得一个蓝牙管理服务的代理对象,进而获得iGatt,同样,iGatt也是一个Binder代理对象,这是一个非常关键的对象,后面会详细讲。然后调用了 BluetoothGatt的connect()方法,需要注意这里有一个参数autoConnect,如果为false,则表示直接连接,true表示自动连接,意思是等到设备可用,则会自动连接上。
接下来看gatt.connect()的实现。
<aosp>/frameworks/base/core/java/android/bluetooth/BluetoothGatt.java
------
boolean connect(Boolean autoConnect, BluetoothGattCallback callback,
Handler handler) {
synchronized (mStateLock) {
// 判断当前连接状态
if (mConnState != CONN_STATE_IDLE) {
throw new IllegalStateException("Not idle");
}
mConnState = CONN_STATE_CONNECTING;
}
mAutoConnect = autoConnect;
// 这里向底层注册上层的应用
if (!registerApp(callback, handler)) {
synchronized (mStateLock) {
mConnState = CONN_STATE_IDLE;
}
Log.e(TAG, "Failed to register callback");
return false;
}
// The connection will continue in the onClientRegistered callback
return true;
}这里面关键的一句是registerApp(callback),这是向底层注册App,底层就知道有App在使用蓝牙,有蓝牙消息的时候,就通过回调通知上层的App。BLE几乎所有操作都是通过异步回调实现的,即通过这个你自定义的 BluetoothGattCallback来通知你的应用。接下来继续看registerApp():
<aosp>/frameworks/base/core/java/android/bluetooth/BluetoothGatt.java
------
private boolean registerApp(BluetoothGattCallback callback, Handler handler) {
return registerApp(callback, handler, false);
}
private boolean registerApp(BluetoothGattCallback callback, Handler handler,
boolean eatt_support) {
if (DBG) Log.d(TAG, "registerApp()");
if (mService == null) return false;
mCallback = callback;
mHandler = handler;
UUID uuid = UUID.randomUUID();
if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
try {
mService.registerClient(
new ParcelUuid(uuid), mBluetoothGattCallback, eatt_support, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
return false;
}
return true;
}可以看到,这里调用了mService.registerClient(),这里的mService就是connectGatt创建BluetoothGatt对象时传入的IBluetoothGatt类型的Binder代理对象。对于这个函数的名字为什么叫 registerClient,这是因为,在Binder机制中,被绑定的Service称为服务端,发起绑定的一方往往叫客户端。
在继续往下看registerClient()这个函数之前,我们回忆一下,我们的目标是连接 BLE 设备,到这一步了,还没有看到连接动作的踪影。这是怎么回事?前面我们说过,蓝牙几乎所有的操作都是依靠回调实现,我们先来看一下这里的mBluetoothGatt(class BluetoothGatt)的实现,看源代码中,这个回调对象(mBluetoothGattCallback)非常大,包含所有的 Gatt回调动作,我们这里主要看onClientRegistered()方法(后面会解释为什么会回调onClientRegistered,这里只要知道registerClient()会回调它)。
<aosp>/frameworks/base/core/java/android/bluetooth/BluetoothGatt.java
------
private final IBluetoothGattCallback mBluetoothGattCallback =
new IBluetoothGattCallback.Stub() {
/**
* Application interface registered - app is ready to go
* @hide
*/
@Override
@SuppressLint("AndroidFrameworkRequiresPermission")
public void onClientRegistered(int status, int clientIf) {
mClientIf = clientIf;
if (status != GATT_SUCCESS) {
// 注册客户端失败,通知到应用的callback
runOrQueueCallback(new Runnable() {
@Override
public void run() {
final BluetoothGattCallback callback = mCallback;
if (callback != null) {
callback.onConnectionStateChange(BluetoothGatt.this,
GATT_FAILURE,
BluetoothProfile.STATE_DISCONNECTED);
}
}
});
synchronized (mStateLock) {
mConnState = CONN_STATE_IDLE;
}
return;
}
try {
// 这里开始做真正的连接操作了
mService.clientConnect(mClientIf, mDevice.getAddress(),
!mAutoConnect, mTransport, mOpportunistic,
mPhy, mAttributionSource); // autoConnect is inverse of "isDirect"
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}这个回调方法有两个参数status和clientIf,前者很好理解,就是表示注册客户端是否成功。clientIf表示从底层返回的一个id,用来唯一标识这个客户端,接下来的所有客户端操作请求,都需要带上这个id。 这个回调方法中做的事情比较清晰,特别注意到mService.clientConnect(...),这里开始调用Service接口开始发起连接了。
从代码中可以看到,mService是一个很关键的对象,但是这个对象是从哪里来的呢?
二、应用框架和蓝牙服务的衔接: Binder服务
在第一段代码的分析中就提到了iGatt对象,从BluetoothGatt的构造函数可以看出,其实mService = iGatt,iGatt是IBluetoothGatt接口的Binder。
我们看一下BluetoothAdapter是怎么获得的,BluetoothAdapter.getDefaultAdapter():
<aosp>/frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java
------
public static synchronized BluetoothAdapter getDefaultAdapter() {
if (sAdapter == null) {
IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
if (b != null) {
IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
sAdapter = new BluetoothAdapter(managerService);
} else {
Log.e(TAG, "Bluetooth binder is null");
}
}
return sAdapter;
}这里是一个单例模式,通过系统API ServiceManager.getService() 获得的,这里大致逻辑就是,在系统启动时候,Android会启动一些系统服务。并通过ServiceManager管理这些服务,具体就不往下深究了。这里直接给出结论,这里Binder代理对象对应的本地对象是BluetoothManagerService,代码在 <aosp>/frameworks/base/services/java/com/android/server/BluetoothManagerService.java。
我们看一下怎么从BluetoothManagerService中获取到IBluetoothGatt的Binder本地对象。注意到 BluetoothManagerService中的一个方法:bluetoothStateChangeHandler(),冲方法名就大概可以知道这个方法是在蓝牙状态变化的时候,做一些处理的。跟踪以下这个函数的调用的地方,就能验证我们的猜想是对的。这一块和本文的关系不大,我们现在来看一下bluetoothStateChangeHandler()的具体实现:
<aosp>/frameworks/base/services/java/com/android/server/BluetoothManagerService.java
------
private void bluetoothStateChangeHandler(int prevState, int newState) {
if (prevState != newState) {
//Notify all proxy objects first of adapter state change
if (newState == BluetoothAdapter.STATE_ON || newState == BluetoothAdapter.STATE_OFF) {
boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
&& newState == BluetoothAdapter.STATE_BLE_ON);
if (newState == BluetoothAdapter.STATE_OFF) {
...
} else if (!intermediate_off) {
// connect to GattService
if (mBluetoothGatt != null) {
if (DBG) Slog.d(TAG, "Calling BluetoothGattServiceUp");
onBluetoothGattServiceUp();
} else {
// if (mContext.getPackageManager().hasSystemFeature(
// PackageManager.FEATURE_BLUETOOTH_LE)) {
Intent i = new Intent(IBluetoothGatt.class.getName());
doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT);
}
sendBleStateChanged(prevState, newState);
// Don't broadcase this as std intent
isStandardBroadcast = false;
} else {
...
}
}
}
}看到 if (!intermediate_off) 这个分支中,会绑定到以IBluetoothGatt的类名为Action Name的服务,也就是 action="android.bluetooth.IBluetoothGatt"。我们在<aosp>/packages/apps/Bluetooth这个App的 AndroidManifest.xml中找到如下的声明:
<aosp>/packages/apps/Bluetooth/AndroidManifest.xml ------ <service android:process="@string/process" android:name = ".gatt.GattService" android:enabled="@bool/profile_supported_gatt"> <intent-filter> <action android:name="android.bluetooth.IBluetoothGatt" /> </intent-filter> </service>
doBind原来是绑定到了com.android.bluetooth.gatt.GattService。如果绑定成功,会回调mConnection的 onServiceConnected(),其实现如下:
<aosp>\frameworks\base\services\core\java\com\android\server\BluetoothManagerService.java
------
private class BluetoothServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName className, IBinder service) {
String name = componentName.getClassName();
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
...
if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
msg.arg1 = SERVICE_IBLUETOOTH;
} else if (name.equals("com.android.bluetooth.gatt.GattService")) {
msg.arg1 = SERVICE_IBLUETOOTHGATT;
}
...
msg.obj = service;
mHandler.sendMessage(msg);
}
}如果绑定的类名是GattService,就会发送MESSAGE_BLUETOOTH_SERVICE_CONNECTED消息给mHandler,消息的第一个参数为SERVICE_IBLUETOOTHGATT,我们接下来看mHandler怎么处理的:
<aosp>/frameworks/base\services/core/java/com/android/server/BluetoothManagerService.java
------
private class BluetoothHandler extends Handler {
@Override
public void handleMessage(Message msg) {
if (DBG) Log.d (TAG, "Message: " + msg.what);
switch (msg.what) {
...
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
{
IBinder service = (IBinder) msg.obj;
mBluetoothLock.writeLock().lock();
if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service);
onBluetoothGattServiceUp();
break;
}
...
}
}
}
}最终获得 IBluetoothGatt 的 Binder代理对象,并赋值给mBluetoothGatt,最后通过getBluetoothGatt,返回给前面的BluetoothGatt。
<aosp>/frameworks/base\services/core/java/com/android/server/BluetoothManagerService.java
------
public IBluetoothGatt getBluetoothGatt() {
// sync protection
return mBluetoothGatt;
}至此,通过Binder机制,完成了应用框架API到Service的绑定。别忘了我们的目标:分析BLE连接的流程。通过前面的代码分析我们知道,连接的时候,先调用了mService.registerClient(),在注册成功后,调用了 mService.clientConnect() 真正发起连接。我们知道了,这个mService实际上就是 com.android.bluetooth.gatt.GattService。我们接下来分析这个Service,也就到了蓝牙服务层了。
三、蓝牙服务:com.android.bluetooth.gatt.GattService
蓝牙服务的代码在<aosp>/packages/app/Bluetooth,编译后生成Bluetooth.apk,安装在 /system/app/ 目录下面,GattService运行在com.android.bluetooth进程。接着来看 Binder 的 registerClient() 接口,这个 Binder 是 GattService 的一个内部类:
<aosp>/packages/apps/Bluetooth/src/com/android/bluetooth/gatt/GattService.java
------
private static class BluetoothGattBinder extends IBluetoothGatt.Stub
implements IProfileServiceBinder {
public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback,
boolean eatt_support, AttributionSource attributionSource) {
GattService service = getService();
if (service == null) {
return;
}
service.registerClient(uuid.getUuid(), callback, eatt_support, attributionSource);
}可以看到,实际上这里还是调用了GattService的registerClient方法:
<aosp>/packages/apps/Bluetooth/src/com/android/bluetooth/gatt/GattService.java
------
void registerClient(UUID uuid, IBluetoothGattCallback callback, boolean eatt_support,
AttributionSource attributionSource) {
if (!Utils.checkConnectPermissionForDataDelivery(
this, attributionSource, "GattService registerClient")) {
return;
}
if (DBG) {
Log.d(TAG, "registerClient() - UUID=" + uuid);
}
mClientMap.add(uuid, null, callback, null, this);
// 调用 native 接口
gattClientRegisterAppNative(uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), eatt_support);
}这里首先是把 uuid 以及对应的 callback 保存到一个 mClientMap 中去,这里从名字上我们就能大概清楚这里的作用,这里的 uuid 是客户端的唯一标识,uuid 对应了客户端的回调函数 callback。接下来,调用gattClientRegisterAppNative() 接口向底层协议栈注册客户端,看一下函数定义:
private native void gattClientRegisterAppNative(long appUuidLsb, long appUuidMsb, boolean eatt_support);
这里可以看出,实际上是客户端的标识 -- UUID 注册到底层去,UUID是128 bit,正好用两个long型的参数表示。这个函数是JNI的申明,具体的实现就在对应的 C/C++ 代码中。
四、蓝牙服务和HAL的调用:JNI
上面的 gattClientRegisterAppNative() 对应的 JNI 的代码在哪里呢?通过查看 AndroidManifest.xml,我们知道Bluetooth 的自定义Application是“.btservice.AdapterApp”,里面有这样的代码:
<aosp>/packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterApp.java
------
public class AdapterApp extends Application {
static {
if (DBG) Log.d(TAG,"Loading JNI Library");
System.loadLibrary("bluetooth_jni");
}
}这里是加载了libbluetooth_jni.so 动态库。我们再看jni目录的 Android.mk,这里正好是生成 libbluetooth_jni的编译脚本。这样我们就知道了对应的 C/C++ 代码在com_android_bluetooth_gatt.cpp。
<aosp>/packages/apps/Bluetooth/jni/com_android_bluetooth_gatt.cpp
------
static JNINativeMethod sMethods[] = {
...
{"gattClientRegisterAppNative", "(JJZ)V",
(void*)gattClientRegisterAppNative},
...
};这是注册JN 函数的标准方法,也是在该cpp,可以找到对应的函数实现。
static void gattClientRegisterAppNative(JNIEnv* env, jobject object,
jlong app_uuid_lsb, jlong app_uuid_msb,
jboolean eatt_support) {
if (!sGattIf) return;
Uuid uuid = from_java_uuid(app_uuid_msb, app_uuid_lsb);
sGattIf->client->register_client(uuid, eatt_support);
}这里调用了sGattIf的client的 register_client()方法,这里还是把客户端的标识 UUID 传递下去。这里的 sGattIf是什么呢?
static const btgatt_interface_t *sGattIf = NULL;
它是一个 btgatt_interface_t 类型的变量,sGattIf 的初始化在 initializeNative() 中,这个函数在 GattService.start() 方法中被调用了,这个函数定义如下:
<aosp>/packages/apps/Bluetooth/jni/com_android_bluetooth_gatt.cpp
------
static const btgatt_interface_t* sGattIf = NULL;
static const bt_interface_t* btIf;
static void initializeNative(JNIEnv* env, jobject object) {
if (btIf) return;
btIf = getBluetoothInterface();
...
sGattIf =
(btgatt_interface_t*)btIf->get_profile_interface(BT_PROFILE_GATT_ID);
if (sGattIf == NULL) {
error("Failed to get Bluetooth GATT Interface");
return;
}
...
}通过以上代码,能知道sGattIf来自btIf,btIf是个指向bt_interface_t结构的指针,值来自getBluetoothInterface()。getBluetoothInterface简单返回一个全局变量sBluetoothInterface,而赋值sBluetoothInterface发生在classInitNative。
<aosp>/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp
------
static const bt_interface_t* sBluetoothInterface = NULL;
const bt_interface_t* getBluetoothInterface() { return sBluetoothInterface; }
static void classInitNative(JNIEnv* env, jclass clazz) {
...
if (hal_util_load_bt_library((bt_interface_t const**)&sBluetoothInterface)) {
ALOGE("No Bluetooth Library found");
}
}com.android.bluetooth在构造“.btservice.AdapterService”这个service时会调用classInitNative,进而给sBluetoothInterface赋值。这个赋值时机发生在Android启动时的初始化阶段。给sBluetoothInterface赋值的函数是hal_util_load_bt_library。
<aosp>/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp
------
int hal_util_load_bt_library(const bt_interface_t** interface) {
const char* sym = BLUETOOTH_INTERFACE_STRING;
bt_interface_t* itf = nullptr;
// The library name is not set by default, so the preset library name is used.
void* handle = dlopen("libbluetooth.so", RTLD_NOW);
if (!handle) {
const char* err_str = dlerror();
ALOGE("%s: failed to load Bluetooth library, error=%s", __func__,
err_str ? err_str : "error unknown");
goto error;
}
// Get the address of the bt_interface_t.
itf = (bt_interface_t*)dlsym(handle, sym);
if (!itf) {
ALOGE("%s: failed to load symbol from Bluetooth library %s", __func__, sym);
goto error;
}
// Success.
ALOGI("%s: loaded Bluetooth library successfully", __func__);
*interface = itf;
return 0;
error:
*interface = NULL;
if (handle) dlclose(handle);
return -EINVAL;
}HAL模块会被编译成一个*.so。一般来说,HAL模块为让它人使用,需要向外export一个和struct hw_module_t相关的变量,使用者则调用hw_get_module得到这个变量。但是,bt_interface_t在定义上和hw_module_t没关系,但逻辑上差不多。
- 蓝牙HAL模块被编译成libbluetooth.so。依协议,libbluetooth.so必须向外EXPORT_SYMBOL一个bt_interface_t类型全局变量。
- (hal_util_load_bt_library)dlopen打开libbluetooth.so
- (hal_util_load_bt_library)用dlsym得到libbluetooth.so中那个bt_interface_t类型的变量,并让itf指向这个变量,也就是sBluetoothInterface。
已经知道libbluetooth.so必须向外EXPORT_SYMBOL一个bt_interface_t类型全局变量,那这变量是什么。
<aosp>/system/bt/btif/src/bluetooth.cc
------
EXPORT_SYMBOL bt_interface_t bluetoothInterface = {
sizeof(bluetoothInterface),
init,
enable,
disable,
cleanup,
...
get_profile_interface, // get_profile_interface
...
};JNI中的sBluetoothInterface就是这个libbluetooth.so中的bluetoothInterface全局变量,为得到sGattIf,JNI调用btIf->get_profile_interface(BT_PROFILE_GATT_ID))。
<aosp>/system/bt/btif/src/bluetooth.c
------
static const void* get_profile_interface(const char* profile_id) {
LOG_INFO("%s: id = %s", __func__, profile_id);
......
// BT_PROFILE_GATT_ID是个宏,它的值是字符串:gatt
if (is_profile(profile_id, BT_PROFILE_GATT_ID))
return btif_gatt_get_interface();
return NULL;
}
<aosp>/system/bt/btif/src/btif_gatt.cc
------
static btgatt_interface_t btgattInterface = {
.size = sizeof(btgattInterface),
.init = btif_gatt_init,
.cleanup = btif_gatt_cleanup,
.client = &btgattClientInterface,
.server = &btgattServerInterface,
.scanner = nullptr, // filled in btif_gatt_get_interface
.advertiser = nullptr // filled in btif_gatt_get_interface
};
const btgatt_interface_t* btif_gatt_get_interface() {
btgattInterface.scanner = get_ble_scanner_instance();
btgattInterface.advertiser = get_ble_advertiser_instance();
return &btgattInterface;
}然后在btif_gatt_client.c,找到btgattClientInterface具体的实现。
<aosp>/system/bt/btif/src/btif_gatt_client.cc
------
const btgatt_client_interface_t btgattClientInterface = {
btif_gattc_register_app, // => register_client
btif_gattc_unregister_app, // => unregister_client
btif_gattc_open, // => connect
btif_gattc_close, // => disconnect
...
};于是可得出结论,针对JNI层中的“sGattIf->client->register_client(&uuid)”,sGattIf对应着HAL中的btgattInterface,sGattIf->client对应着btgattClientInterface结构,register_client是该结构中的btif_gattc_register_app字段,当然,它的类型是函数。