- 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字段,当然,它的类型是函数。