Android 蓝牙 BLE 扫描 Native 层架构与扫描流程剖析

Android 蓝牙 BLE 扫描 Native 层架构与扫描流程剖析
博主简介

byte轻骑兵,现就职于国内知名科技企业,专注于嵌入式系统研发,深耕 Android、Linux、RTOS、通信协议、AIoT、物联网及 C/C++ 等领域。乐于技术分享与交流,欢迎关注互动!

📌 主页与联系方式ZEEKLOG:https://blog.ZEEKLOG.net/weixin_37800531知乎:https://www.zhihu.com/people/38-72-36-20-51微信公众号:嵌入式硬核研究所邮箱[email protected](技术咨询或合作请备注需求)

⚠️ 版权声明

本文为原创内容,未经授权禁止转载。商业合作或内容授权请联系邮箱并备注来意。

本文基于 Android 蓝牙源码中 BLE 扫描相关的 Native 层代码,以scanInitializeNative为入口,系统梳理 BLE 扫描从 JNI 层到 BTIF 层、GD Shim 层再到 HCI 层的核心实现逻辑;重点分析GD Shim 层作为新老架构桥接层的设计思路,以及BleScannerInterfaceImpl的承上启下核心作用;解析扫描实例的懒加载单例创建、回调注册与分发、各层接口的解耦与交互机制,为 Android 蓝牙 BLE 扫描的 Native 层开发、问题定位提供核心参考。


一、概述

本文分析的代码均来自 Android 蓝牙源码,覆盖 JNI、BTIF、GD Shim、HCI 四大核心层,是 Android 蓝牙 BLE 扫描 Native 层的核心实现代码。整体以 BLE 扫描的初始化接口桥接为两条主线:以scanInitializeNative(JNI 层)为扫描初始化入口,负责对接上层 Java 并完成扫描实例的初步初始化与回调注册;BTIF 层通过btif_gatt_get_interface提供统一的 GATT 扫描接口,完成扫描、广播等实例的赋值;GD Shim 层是新架构(GD)与传统蓝牙架构的核心桥接层,通过get_ble_scanner_instance实现扫描实例的懒加载单例创建,其核心类BleScannerInterfaceImpl是整个流程的核心载体;HCI 层提供底层扫描回调基类,由 Shim 层实现并完成扫描事件的上层分发。各层通过抽象接口解耦,BleScannerInterfaceImpl同时实现上层BleScannerInterface和下层 HCIScanningCallback,承上启下处理所有扫描相关的接口调用与事件回调。


二、源码剖析

scanInitializeNative

packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_gatt.cpp static void scanInitializeNative(JNIEnv* env, jobject object) { // 获取写锁,防止多线程同时初始化扫描模块 std::unique_lock<std::shared_mutex> lock(callbacks_mutex); // 获取底层BLE扫描器单例并注册JNI回调适配器 sScanner = bluetooth::shim::get_ble_scanner_instance(); sScanner->RegisterCallbacks(JniScanningCallbacks::GetInstance()); // 清理旧Java回调对象的全局引用,避免内存泄漏 if (mScanCallbacksObj != NULL) { log::warn("Cleaning up scan callback object"); env->DeleteGlobalRef(mScanCallbacksObj); mScanCallbacksObj = NULL; } // 创建新的Java回调对象全局引用,确保在JNI层不会被回收 mScanCallbacksObj = env->NewGlobalRef(object); }

初始化蓝牙BLE扫描模块,通过线程安全的读写锁保护初始化过程,管理Java回调对象的生命周期(清理旧引用并创建新全局引用),建立底层C++扫描器与JNI回调适配器的关联,确保扫描事件能正确从Native层传递到Java层。

class JniScanningCallbacks

packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_gatt.cpp // JNI回调适配器类:将底层C++扫描事件桥接到Java层 class JniScanningCallbacks : ScanningCallbacks { public: // 单例模式获取实例,确保全局只有一个回调处理器 static ScanningCallbacks* GetInstance() { static ScanningCallbacks* instance = new JniScanningCallbacks(); return instance; } // 扫描器注册完成回调 void OnScannerRegistered(const Uuid app_uuid, uint8_t scannerId, uint8_t status) { std::shared_lock<std::shared_mutex> lock(callbacks_mutex); // 读锁保护,允许多线程并发读取 CallbackEnv sCallbackEnv(__func__); // 获取JNI环境,自动处理线程附加 if (!sCallbackEnv.valid() || !mScanCallbacksObj) return; // 环境验证 sCallbackEnv->CallVoidMethod(mScanCallbacksObj, method_onScannerRegistered, status, scannerId, UUID_PARAMS(app_uuid)); } // 扫描参数设置完成回调 void OnSetScannerParameterComplete(uint8_t scannerId, uint8_t status) { std::shared_lock<std::shared_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || !mScanCallbacksObj) return; sCallbackEnv->CallVoidMethod(mScanCallbacksObj, method_onScanParamSetupCompleted, status, scannerId); } // 扫描结果回调(核心函数) void OnScanResult(uint16_t event_type, uint8_t addr_type, RawAddress bda, uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid, int8_t tx_power, int8_t rssi, uint16_t periodic_adv_int, std::vector<uint8_t> adv_data) { std::shared_lock<std::shared_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || !mScanCallbacksObj) return; // 蓝牙地址转换:RawAddress → jstring ScopedLocalRef<jstring> address(sCallbackEnv.get(), bdaddr2newjstr(sCallbackEnv.get(), &bda)); // 广告数据转换:vector<uint8_t> → jbyteArray ScopedLocalRef<jbyteArray> jb(sCallbackEnv.get(), sCallbackEnv->NewByteArray(adv_data.size())); sCallbackEnv->SetByteArrayRegion(jb.get(), 0, adv_data.size(), (jbyte*)adv_data.data()); // TODO:处理原始地址,目前使用空地址占位 char empty_address[18] = "00:00:00:00:00:00"; ScopedLocalRef<jstring> fake_address(sCallbackEnv.get(), sCallbackEnv->NewStringUTF(empty_address)); // 调用Java层方法,传递所有扫描结果参数 sCallbackEnv->CallVoidMethod(mScanCallbacksObj, method_onScanResult, event_type, addr_type, address.get(), primary_phy, secondary_phy, advertising_sid, tx_power, rssi, periodic_adv_int, jb.get(), fake_address.get()); } // 广告跟踪发现/丢失回调(蓝牙5.0扩展扫描功能) void OnTrackAdvFoundLost(AdvertisingTrackInfo track_info) { std::shared_lock<std::shared_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || !mScanCallbacksObj) { log::error("sCallbackEnv not valid or no mScanCallbacksObj."); return; } // 地址转换 ScopedLocalRef<jstring> address( sCallbackEnv.get(), bdaddr2newjstr(sCallbackEnv.get(), &track_info.advertiser_address)); // 广告数据和扫描响应数据转换 ScopedLocalRef<jbyteArray> jb_adv_pkt(sCallbackEnv.get(), sCallbackEnv->NewByteArray(track_info.adv_packet_len)); ScopedLocalRef<jbyteArray> jb_scan_rsp( sCallbackEnv.get(), sCallbackEnv->NewByteArray(track_info.scan_response_len)); sCallbackEnv->SetByteArrayRegion(jb_adv_pkt.get(), 0, track_info.adv_packet_len, (jbyte*)track_info.adv_packet.data()); sCallbackEnv->SetByteArrayRegion(jb_scan_rsp.get(), 0, track_info.scan_response_len, (jbyte*)track_info.scan_response.data()); // 调用Java方法创建跟踪广告对象,再回调给Java层 ScopedLocalRef<jobject> trackadv_obj( sCallbackEnv.get(), sCallbackEnv->CallObjectMethod( mScanCallbacksObj, method_createOnTrackAdvFoundLostObject, track_info.scanner_id, track_info.adv_packet_len, jb_adv_pkt.get(), track_info.scan_response_len, jb_scan_rsp.get(), track_info.filter_index, track_info.advertiser_state, track_info.advertiser_info_present, address.get(), track_info.advertiser_address_type, track_info.tx_power, track_info.rssi, track_info.time_stamp)); if (NULL != trackadv_obj.get()) { sCallbackEnv->CallVoidMethod(mScanCallbacksObj, method_onTrackAdvFoundLost, trackadv_obj.get()); } } // 批量扫描报告回调 void OnBatchScanReports(int client_if, int status, int report_format, int num_records, std::vector<uint8_t> data) { std::shared_lock<std::shared_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || !mScanCallbacksObj) return; ScopedLocalRef<jbyteArray> jb(sCallbackEnv.get(), sCallbackEnv->NewByteArray(data.size())); sCallbackEnv->SetByteArrayRegion(jb.get(), 0, data.size(), (jbyte*)data.data()); sCallbackEnv->CallVoidMethod(mScanCallbacksObj, method_onBatchScanReports, status, client_if, report_format, num_records, jb.get()); } // 批量扫描阈值越过回调 void OnBatchScanThresholdCrossed(int client_if) { std::shared_lock<std::shared_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || !mScanCallbacksObj) return; sCallbackEnv->CallVoidMethod(mScanCallbacksObj, method_onBatchScanThresholdCrossed, client_if); } // 周期性扫描同步开始回调(蓝牙5.0+) void OnPeriodicSyncStarted(int reg_id, uint8_t status, uint16_t sync_handle, uint8_t sid, uint8_t address_type, RawAddress address, uint8_t phy, uint16_t interval) override { std::shared_lock<std::shared_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; if (!mPeriodicScanCallbacksObj) { // 使用专门的周期性扫描回调对象 log::error("mPeriodicScanCallbacksObj is NULL. Return."); return; } ScopedLocalRef<jstring> addr(sCallbackEnv.get(), bdaddr2newjstr(sCallbackEnv.get(), &address)); sCallbackEnv->CallVoidMethod(mPeriodicScanCallbacksObj, method_onSyncStarted, reg_id, sync_handle, sid, address_type, addr.get(), phy, interval, status); } // 周期性同步报告回调 void OnPeriodicSyncReport(uint16_t sync_handle, int8_t tx_power, int8_t rssi, uint8_t data_status, std::vector<uint8_t> data) override { std::shared_lock<std::shared_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || !mPeriodicScanCallbacksObj) return; ScopedLocalRef<jbyteArray> jb(sCallbackEnv.get(), sCallbackEnv->NewByteArray(data.size())); sCallbackEnv->SetByteArrayRegion(jb.get(), 0, data.size(), (jbyte*)data.data()); sCallbackEnv->CallVoidMethod(mPeriodicScanCallbacksObj, method_onSyncReport, sync_handle, tx_power, rssi, data_status, jb.get()); } // 周期性同步丢失回调 void OnPeriodicSyncLost(uint16_t sync_handle) override { std::shared_lock<std::shared_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || !mPeriodicScanCallbacksObj) return; sCallbackEnv->CallVoidMethod(mPeriodicScanCallbacksObj, method_onSyncLost, sync_handle); } // 周期性同步传输回调 void OnPeriodicSyncTransferred(int pa_source, uint8_t status, RawAddress address) override { std::shared_lock<std::shared_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; if (!mPeriodicScanCallbacksObj) { log::error("mPeriodicScanCallbacksObj is NULL. Return."); return; } ScopedLocalRef<jstring> addr(sCallbackEnv.get(), bdaddr2newjstr(sCallbackEnv.get(), &address)); sCallbackEnv->CallVoidMethod(mPeriodicScanCallbacksObj, method_onSyncTransferredCallback, pa_source, status, addr.get()); } // BIG信息报告回调(蓝牙5.2+,支持广播同步组) void OnBigInfoReport(uint16_t sync_handle, bool encrypted) { std::shared_lock<std::shared_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid()) return; if (!mPeriodicScanCallbacksObj) { log::error("mPeriodicScanCallbacksObj is NULL. Return."); return; } sCallbackEnv->CallVoidMethod(mPeriodicScanCallbacksObj, method_onBigInfoReport, sync_handle, encrypted); } };

作为JNI桥接层,将底层C++蓝牙扫描事件(注册完成、扫描结果、批量报告、周期性同步等)安全地传递给Java层,通过读写锁保护并发访问,使用RAII类管理JNI引用,支持从BLE 4.x到蓝牙5.2+的全特性回调转发。

关键设计:单例模式:GetInstance()确保全局唯一回调处理器线程安全:所有回调方法使用std::shared_lock读锁,允许多事件并发处理内存安全:CallbackEnvScopedLocalRef自动管理JNI环境/引用生命周期协议演进支持:分层处理基础扫描(OnScanResult)、扩展扫描(OnTrackAdvFoundLost)和蓝牙5.x周期性同步(OnPeriodicSync*)错误处理:每个回调都验证JNI环境和Java对象有效性,防止空指针异常

btif_gatt_get_interface

packages/modules/Bluetooth/system/btif/src/btif_gatt.cc /******************************************************************************* * * Function btif_gatt_get_interface * * Description Get the gatt callback interface * * Returns btgatt_interface_t * ******************************************************************************/ const btgatt_interface_t* btif_gatt_get_interface() { // TODO(jpawlowski) right now initializing advertiser field in static // structure cause explosion of dependencies. It must be initialized here // until those dependencies are properly abstracted for tests. // 延迟初始化:解决循环依赖问题 // scanner、advertiser、distance_measurement_manager 需要在运行时获取实例 // 避免编译时的依赖爆炸,同时便于单元测试 btgattInterface.scanner = get_ble_scanner_instance(); // 获取BLE扫描器实例 btgattInterface.advertiser = bluetooth::shim::get_ble_advertiser_instance(); // 获取BLE广播器实例 btgattInterface.distance_measurement_manager = bluetooth::shim::get_distance_measurement_instance(); // 获取距离测量管理器实例 return &btgattInterface; // 返回完整的GATT接口结构体 } // 全局GATT接口结构体定义 // 采用C风格结构体初始化,部分字段延迟初始化 static btgatt_interface_t btgattInterface = { .size = sizeof(btgattInterface), // 结构体大小,用于版本兼容性检查 // 基础生命周期管理函数 .init = btif_gatt_init, .cleanup = btif_gatt_cleanup, // GATT客户端、服务端接口 .client = &btgattClientInterface, .server = &btgattServerInterface, // 延迟初始化的BLE角色接口(在btif_gatt_get_interface中填充) .scanner = nullptr, // BLE扫描器接口,后初始化以避免依赖问题 .advertiser = nullptr // BLE广播器接口,后初始化以避免依赖问题 };

提供统一的蓝牙GATT功能接口获取函数,通过延迟初始化模式解决依赖循环问题,将BLE扫描器、广播器和距离测量管理器等组件聚合到单一接口结构中,实现GATT角色(客户端/服务端)和BLE角色(扫描器/广播器)的统一管理。

延迟初始化模式scanneradvertiserdistance_measurement_manager字段在运行时通过get_ble_scanner_instance()等函数动态获取实例,避免了编译时依赖循环模块化设计:通过btgatt_interface_t结构体将GATT功能分为clientserverscanneradvertiser等独立模块,符合单一职责原则版本兼容.size = sizeof(btgattInterface)字段允许接口版本检测,确保二进制兼容性shim层抽象:通过bluetooth::shim命名空间获取实例,屏蔽底层HIDL/AIDL实现差异

get_ble_scanner_instance

packages/modules/Bluetooth/system/btif/src/btif_ble_scanner.cc BleScannerInterface* get_ble_scanner_instance() { // 通过shim中间层获取BLE扫描器实例,实现依赖解耦 return bluetooth::shim::get_ble_scanner_instance(); } // le_scanning_manager.cc - shim层实现 // 全局BLE扫描器实例指针,采用延迟初始化策略 BleScannerInterfaceImpl* bt_le_scanner_instance = nullptr; // shim层API:获取或创建BLE扫描器单例实例 BleScannerInterface* bluetooth::shim::get_ble_scanner_instance() { // 双重检查锁定模式:先检查指针,再决定是否创建 if (bt_le_scanner_instance == nullptr) { // 首次调用时创建实例,后续调用直接返回 bt_le_scanner_instance = new BleScannerInterfaceImpl(); } return bt_le_scanner_instance; // 返回实现类的基类指针 }

BLE扫描器实例的单例获取模式,通过shim中间层进行解耦,get_ble_scanner_instance()函数确保全局只有一个BleScannerInterfaceImpl实例,为上层提供统一的BLE扫描操作接口。

class BleScannerInterfaceImpl

packages/modules/Bluetooth/system/main/shim/ble_scanner_interface_impl.h /* * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Gd shim layer to legacy le scanner * Gd(Google蓝牙新架构)与旧版LE扫描器之间的适配层 */ #pragma once #include <queue> #include <set> #include <vector> #include "hci/le_scanning_callback.h" #include "include/hardware/ble_scanner.h" #include "types/ble_address_with_type.h" #include "types/bluetooth/uuid.h" #include "types/raw_address.h" namespace bluetooth { namespace shim { // 全局默认扫描回调,用于桥接旧版回调系统 extern ::ScanningCallbacks* default_scanning_callback; // Microsoft广告监控回调封装类 class MsftCallbacks { public: using MsftAdvMonitorAddCallback = base::Callback<void(uint8_t /* monitor_handle */, uint8_t /* status */)>; using MsftAdvMonitorRemoveCallback = base::Callback<void(uint8_t /* status */)>; using MsftAdvMonitorEnableCallback = base::Callback<void(uint8_t /* status */)>; MsftAdvMonitorAddCallback Add; // 广告监控器添加回调 MsftAdvMonitorRemoveCallback Remove; // 广告监控器移除回调 MsftAdvMonitorEnableCallback Enable; // 广告监控器启用回调 }; // 核心适配器类:实现新旧架构的双向桥接 class BleScannerInterfaceImpl : public ::BleScannerInterface, // 旧版接口 public bluetooth::hci::ScanningCallback { // 新版Gd回调接口 public: ~BleScannerInterfaceImpl() override {} void Init(); // 初始化适配器 // ::BleScannerInterface 旧版接口实现 void RegisterScanner(const bluetooth::Uuid& uuid, RegisterCallback) override; void Unregister(int scanner_id) override; void Scan(bool start) override; void ScanFilterParamSetup(uint8_t client_if, uint8_t action, uint8_t filter_index, std::unique_ptr<btgatt_filt_param_setup_t> filt_param, FilterParamSetupCallback cb) override; void ScanFilterAdd(int filter_index, std::vector<ApcfCommand> filters, FilterConfigCallback cb) override; void ScanFilterClear(int filter_index, FilterConfigCallback cb) override; void ScanFilterEnable(bool enable, EnableCallback cb) override; bool IsMsftSupported() override; // 检查Microsoft扩展支持 void MsftAdvMonitorAdd(MsftAdvMonitor monitor, MsftAdvMonitorAddCallback cb) override; void MsftAdvMonitorRemove(uint8_t monitor_handle, MsftAdvMonitorRemoveCallback cb) override; void MsftAdvMonitorEnable(bool enable, MsftAdvMonitorEnableCallback cb) override; void SetScanParameters(uint8_t scan_type, int scanner_id_1m, int scan_interval_1m, int scan_window_1m, int scanner_id_coded, int scan_interval_coded, int scan_window_coded, int scan_phy) override; void BatchscanConfigStorage(int client_if, int batch_scan_full_max, int batch_scan_trunc_max, int batch_scan_notify_threshold, Callback cb) override; void BatchscanEnable(int scan_mode, int scan_interval, int scan_window, int addr_type, int discard_rule, Callback cb) override; void BatchscanDisable(Callback cb) override; void BatchscanReadReports(int client_if, int scan_mode) override; void StartSync(uint8_t sid, RawAddress address, uint16_t skip, uint16_t timeout, int reg_id) override; // 启动周期性扫描同步 void StopSync(uint16_t handle) override; void CancelCreateSync(uint8_t sid, RawAddress address) override; void TransferSync(RawAddress address, uint16_t service_data, uint16_t sync_handle, int pa_source) override; void TransferSetInfo(RawAddress address, uint16_t service_data, uint8_t adv_handle, int pa_source) override; void SyncTxParameters(RawAddress addr, uint8_t mode, uint16_t skip, uint16_t timeout, int reg_id) override; // bluetooth::hci::ScanningCallback Gd新版回调接口 void RegisterCallbacks(ScanningCallbacks* callbacks); void OnScannerRegistered(const bluetooth::hci::Uuid app_uuid, bluetooth::hci::ScannerId scanner_id, ScanningStatus status) override; void OnSetScannerParameterComplete(bluetooth::hci::ScannerId scanner_id, ScanningStatus status) override; void OnScanResult(uint16_t event_type, uint8_t address_type, bluetooth::hci::Address address, uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid, int8_t tx_power, int8_t rssi, uint16_t periodic_advertising_interval, std::vector<uint8_t> advertising_data) override; // 扫描结果回调 void OnTrackAdvFoundLost( bluetooth::hci::AdvertisingFilterOnFoundOnLostInfo on_found_on_lost_info) override; void OnBatchScanReports(int client_if, int status, int report_format, int num_records, std::vector<uint8_t> data) override; void OnBatchScanThresholdCrossed(int client_if) override; void OnTimeout() override; void OnFilterEnable(bluetooth::hci::Enable enable, uint8_t status) override; void OnFilterParamSetup(uint8_t available_spaces, bluetooth::hci::ApcfAction action, uint8_t status) override; void OnFilterConfigCallback(bluetooth::hci::ApcfFilterType filter_type, uint8_t available_spaces, bluetooth::hci::ApcfAction action, uint8_t status) override; void OnPeriodicSyncStarted(int reg_id, uint8_t status, uint16_t sync_handle, uint8_t advertising_sid, bluetooth::hci::AddressWithType address_with_type, uint8_t phy, uint16_t interval) override; void OnPeriodicSyncReport(uint16_t sync_handle, int8_t tx_power, int8_t rssi, uint8_t status, std::vector<uint8_t> data) override; void OnPeriodicSyncLost(uint16_t sync_handle) override; void OnPeriodicSyncTransferred(int pa_source, uint8_t status, bluetooth::hci::Address address) override; void OnBigInfoReport(uint16_t sync_handle, bool encrypted) override; // 回调桥接:将Gd回调转发给旧版回调系统 ::ScanningCallbacks* scanning_callbacks_ = default_scanning_callback; void OnMsftAdvMonitorAdd(uint8_t monitor_handle, bluetooth::hci::ErrorCode status); void OnMsftAdvMonitorRemove(bluetooth::hci::ErrorCode status); void OnMsftAdvMonitorEnable(bool enable, bluetooth::hci::ErrorCode status); MsftCallbacks msft_callbacks_; // Microsoft扩展回调 private: // 解析APCF过滤命令 bool parse_filter_command(bluetooth::hci::AdvertisingPacketContentFilterCommand& advertising_packet_content_filter_command, ApcfCommand apcf_command); // 处理远程设备属性 void handle_remote_properties(RawAddress bd_addr, tBLE_ADDR_TYPE addr_type, std::vector<uint8_t> advertising_data); // 扫描结果处理统一入口 void on_scan_result(uint16_t event_type, uint8_t address_type, bluetooth::hci::Address address, uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid, int8_t tx_power, int8_t rssi, uint16_t periodic_advertising_interval, std::vector<uint8_t> advertising_data); // 地址缓存,用于去重 class AddressCache { public: void init(void); void add(const RawAddress& p_bda); bool find(const RawAddress& p_bda); private: // 所有访问都应在jni线程上进行 std::set<RawAddress> remote_bdaddr_cache_; // 快速查找 std::queue<RawAddress> remote_bdaddr_cache_ordered_; // 先进先出顺序 const size_t remote_bdaddr_cache_max_size_ = 1024; // 最大缓存大小 } address_cache_; }; } // namespace shim } // namespace bluetooth

作为Gd蓝牙栈与Legacy蓝牙栈之间的适配层,BleScannerInterfaceImpl实现了完整的BLE扫描功能,包括设备发现、扫描过滤器管理、批量扫描、周期性广播同步等,通过双继承设计既向上层提供统一接口又接收底层HCI事件。

关键设计:双继承架构:同时继承::BleScannerInterface(服务接口)和bluetooth::hci::ScanningCallback(事件回调)完整协议支持:覆盖BLE 4.x到5.2+的所有扫描相关功能,包括基础扫描、APCF过滤器、批量扫描、周期性广播同步、Microsoft扩展地址缓存机制:内置AddressCache类管理已发现设备地址,使用std::set+std::queue实现LRU策略的1024容量缓存线程安全考虑:注释明确要求地址缓存操作必须在JNI线程执行扩展性设计:通过MsftCallbacks支持厂商特定扩展功能

class BleScannerInterface

packages/modules/Bluetooth/system/include/hardware/ble_scanner.h /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_INCLUDE_BLE_SCANNER_H #define ANDROID_INCLUDE_BLE_SCANNER_H #include <stdint.h> #include <memory> #include <vector> #include "bt_common_types.h" #include "bt_gatt_client.h" #include "bt_gatt_types.h" #include "types/bluetooth/uuid.h" #include "types/raw_address.h" // 广告跟踪信息结构体,用于扩展扫描功能(蓝牙5.0+) class AdvertisingTrackInfo { public: // MSFT广告监视器相关字段(Microsoft扩展) uint8_t monitor_handle; uint8_t scanner_id; uint8_t filter_index; uint8_t advertiser_state; // 广告状态:发现/丢失 uint8_t advertiser_info_present; // 广告信息是否存在 RawAddress advertiser_address; // 广告设备地址 uint8_t advertiser_address_type; // 地址类型:公有/私有 uint8_t tx_power; // 发射功率 int8_t rssi; // 接收信号强度 uint16_t time_stamp; // 时间戳 uint8_t adv_packet_len; // 广告包长度 std::vector<uint8_t> adv_packet; // 广告包数据 uint8_t scan_response_len; // 扫描响应长度 std::vector<uint8_t> scan_response; // 扫描响应数据 }; /** * LE扫描回调接口类(纯虚类) * 所有回调都在JNI线程上调用,确保线程安全 */ class ScanningCallbacks { public: virtual ~ScanningCallbacks() = default; // 扫描器注册完成回调 virtual void OnScannerRegistered(const bluetooth::Uuid app_uuid, uint8_t scannerId, uint8_t status) = 0; // 扫描参数设置完成回调 virtual void OnSetScannerParameterComplete(uint8_t scannerId, uint8_t status) = 0; // 扫描结果回调(核心函数) virtual void OnScanResult(uint16_t event_type, uint8_t addr_type, RawAddress bda, uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid, int8_t tx_power, int8_t rssi, uint16_t periodic_adv_int, std::vector<uint8_t> adv_data) = 0; // 广告跟踪发现/丢失回调(蓝牙5.0扩展扫描) virtual void OnTrackAdvFoundLost(AdvertisingTrackInfo advertising_track_info) = 0; // 批量扫描报告回调 virtual void OnBatchScanReports(int client_if, int status, int report_format, int num_records, std::vector<uint8_t> data) = 0; // 批量扫描阈值越过回调 virtual void OnBatchScanThresholdCrossed(int client_if) = 0; // 周期性扫描同步开始回调(蓝牙5.0+) virtual void OnPeriodicSyncStarted(int reg_id, uint8_t status, uint16_t sync_handle, uint8_t advertising_sid, uint8_t address_type, RawAddress address, uint8_t phy, uint16_t interval) = 0; // 周期性同步报告回调 virtual void OnPeriodicSyncReport(uint16_t sync_handle, int8_t tx_power, int8_t rssi, uint8_t status, std::vector<uint8_t> data) = 0; // 周期性同步丢失回调 virtual void OnPeriodicSyncLost(uint16_t sync_handle) = 0; // 周期性同步传输回调 virtual void OnPeriodicSyncTransferred(int pa_source, uint8_t status, RawAddress address) = 0; // BIG信息报告回调(蓝牙5.2+,支持广播同步组) virtual void OnBigInfoReport(uint16_t sync_handle, bool encrypted) = 0; }; // BLE扫描器接口类(纯虚类),定义了扫描器需要实现的所有操作 class BleScannerInterface { public: virtual ~BleScannerInterface() = default; // 回调类型定义,使用base::Callback进行类型安全回调封装 using RegisterCallback = base::Callback<void(uint8_t /* scanner_id */, uint8_t /* btm_status */)>; using Callback = base::Callback<void(uint8_t /* btm_status */)>; using EnableCallback = base::Callback<void(uint8_t /* action */, uint8_t /* btm_status */)>; using FilterParamSetupCallback = base::Callback<void( uint8_t /* avbl_space */, uint8_t /* action_type */, uint8_t /* btm_status */)>; using FilterConfigCallback = base::Callback<void(uint8_t /* filt_type */, uint8_t /* avbl_space */, uint8_t /* action */, uint8_t /* btm_status */)>; using MsftAdvMonitorAddCallback = base::Callback<void(uint8_t /* monitor_handle */, uint8_t /* status */)>; using MsftAdvMonitorRemoveCallback = base::Callback<void(uint8_t /* status */)>; using MsftAdvMonitorEnableCallback = base::Callback<void(uint8_t /* status */)>; // 注册扫描器到栈中 virtual void RegisterScanner(const bluetooth::Uuid& app_uuid, RegisterCallback) = 0; // 从栈中注销扫描器 virtual void Unregister(int scanner_id) = 0; // 启动或停止LE设备扫描 virtual void Scan(bool start) = 0; // 设置扫描过滤器参数 virtual void ScanFilterParamSetup(uint8_t client_if, uint8_t action, uint8_t filt_index, std::unique_ptr<btgatt_filt_param_setup_t> filt_param, FilterParamSetupCallback cb) = 0; // 配置扫描过滤器条件 virtual void ScanFilterAdd(int filter_index, std::vector<ApcfCommand> filters, FilterConfigCallback cb) = 0; // 清除特定过滤索引的所有扫描过滤器条件 virtual void ScanFilterClear(int filt_index, FilterConfigCallback cb) = 0; // 启用/禁用扫描过滤器功能 virtual void ScanFilterEnable(bool enable, EnableCallback cb) = 0; // 检查是否支持Microsoft扩展功能 virtual bool IsMsftSupported() = 0; // 配置MSFT扫描过滤器(广告监视器) virtual void MsftAdvMonitorAdd(MsftAdvMonitor monitor, MsftAdvMonitorAddCallback cb) = 0; // 移除先前添加的MSFT扫描过滤器 virtual void MsftAdvMonitorRemove(uint8_t monitor_handle, MsftAdvMonitorRemoveCallback cb) = 0; // 启用/禁用MSFT扫描过滤器功能 virtual void MsftAdvMonitorEnable(bool enable, MsftAdvMonitorEnableCallback cb) = 0; // 设置LE扫描间隔和窗口(单位:N*0.625毫秒) virtual void SetScanParameters(uint8_t scan_type, int scanner_id_1m, int scan_interval_1m, int scan_window_1m, int scanner_id_coded, int scan_interval_coded, int scan_window_coded, int scan_phy) = 0; // 配置批量扫描存储 virtual void BatchscanConfigStorage(int client_if, int batch_scan_full_max, int batch_scan_trunc_max, int batch_scan_notify_threshold, Callback cb) = 0; // 启用批量扫描 virtual void BatchscanEnable(int scan_mode, int scan_interval, int scan_window, int addr_type, int discard_rule, Callback cb) = 0; // 禁用批量扫描 virtual void BatchscanDisable(Callback cb) = 0; // 读取批量扫描报告 virtual void BatchscanReadReports(int client_if, int scan_mode) = 0; // 启动周期性广播同步(蓝牙5.0+) virtual void StartSync(uint8_t sid, RawAddress address, uint16_t skip, uint16_t timeout, int reg_id) = 0; // 停止周期性广播同步 virtual void StopSync(uint16_t handle) = 0; // 注册扫描回调(被遗忘在接口定义之外,需要实现) virtual void RegisterCallbacks(ScanningCallbacks* callbacks) = 0; // 取消创建同步 virtual void CancelCreateSync(uint8_t sid, RawAddress address) = 0; // 传输同步信息 virtual void TransferSync(RawAddress address, uint16_t service_data, uint16_t sync_handle, int pa_source) = 0; // 传输设置信息 virtual void TransferSetInfo(RawAddress address, uint16_t service_data, uint8_t adv_handle, int pa_source) = 0; // 设置同步传输参数 virtual void SyncTxParameters(RawAddress addr, uint8_t mode, uint16_t skip, uint16_t timeout, int reg_id) = 0; }; #endif /* ANDROID_INCLUDE_BLE_SCANNER_H */

定义了Android蓝牙栈中BLE扫描功能的完整接口规范,包括扫描回调接口ScanningCallbacks和扫描器操作接口BleScannerInterface,涵盖了从基础扫描到蓝牙5.x扩展功能的所有操作,为GATT模块、JNI层和底层实现提供了统一的抽象接口。

class ScanningCallback

packages/modules/Bluetooth/system/gd/hci/le_scanning_callback.h /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <memory> #include <vector> #include "common/callback.h" #include "hci/address_with_type.h" #include "hci/hci_packets.h" #include "hci/uuid.h" namespace bluetooth { namespace hci { using ScannerId = uint8_t; // 扫描器ID类型定义 // Gd架构的广告发现/丢失信息结构体 class AdvertisingFilterOnFoundOnLostInfo { public: // 对于基于MSFT的广告事件,monitor_handle将每个事件与关联的监控器过滤器绑定 uint8_t monitor_handle; uint8_t scanner_id; uint8_t filter_index; uint8_t advertiser_state; AdvtInfoPresent advertiser_info_present; // 使用枚举类型 Address advertiser_address; // Gd架构的地址类型 uint8_t advertiser_address_type; uint8_t tx_power; int8_t rssi; uint16_t time_stamp; std::vector<uint8_t> adv_packet; std::vector<uint8_t> scan_response; }; // Gd架构的扫描回调接口 class ScanningCallback { public: // 扫描状态枚举,包含HCI错误码 enum ScanningStatus { SUCCESS, NO_RESOURCES = 0x80, // 资源不足 INTERNAL_ERROR = 0x85, // 内部错误 ILLEGAL_PARAMETER = 0x87, // 非法参数 }; virtual ~ScanningCallback() = default; // 扫描器注册回调 virtual void OnScannerRegistered(const bluetooth::hci::Uuid app_uuid, ScannerId scanner_id, ScanningStatus status) = 0; // 扫描参数设置完成回调 virtual void OnSetScannerParameterComplete(ScannerId scanner_id, ScanningStatus status) = 0; // 扫描结果回调 virtual void OnScanResult(uint16_t event_type, uint8_t address_type, Address address, uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid, int8_t tx_power, int8_t rssi, uint16_t periodic_advertising_interval, std::vector<uint8_t> advertising_data) = 0; // 广告追踪发现/丢失回调 virtual void OnTrackAdvFoundLost(AdvertisingFilterOnFoundOnLostInfo on_found_on_lost_info) = 0; // 批量扫描报告回调 virtual void OnBatchScanReports(int client_if, int status, int report_format, int num_records, std::vector<uint8_t> data) = 0; // 批量扫描阈值跨越回调 virtual void OnBatchScanThresholdCrossed(int client_if) = 0; // 超时回调 virtual void OnTimeout() = 0; // 过滤器启用回调 virtual void OnFilterEnable(Enable enable, uint8_t status) = 0; // 过滤器参数设置回调 virtual void OnFilterParamSetup(uint8_t available_spaces, ApcfAction action, uint8_t status) = 0; // 过滤器配置回调 virtual void OnFilterConfigCallback(ApcfFilterType filter_type, uint8_t available_spaces, ApcfAction action, uint8_t status) = 0; // 周期性扫描同步开始回调 virtual void OnPeriodicSyncStarted(int request_id, uint8_t status, uint16_t sync_handle, uint8_t advertising_sid, AddressWithType address_with_type, uint8_t phy, uint16_t interval) = 0; // 周期性扫描报告回调 virtual void OnPeriodicSyncReport(uint16_t sync_handle, int8_t tx_power, int8_t rssi, uint8_t status, std::vector<uint8_t> data) = 0; // 周期性扫描丢失回调 virtual void OnPeriodicSyncLost(uint16_t sync_handle) = 0; // 周期性扫描传输回调 virtual void OnPeriodicSyncTransferred(int pa_source, uint8_t status, Address address) = 0; // BIG信息报告回调 virtual void OnBigInfoReport(uint16_t sync_handle, bool encrypted) = 0; }; // 广告包内容过滤器命令结构体 class AdvertisingPacketContentFilterCommand { public: ApcfFilterType filter_type; // 过滤器类型 Address address; // 目标地址 ApcfApplicationAddressType application_address_type; // 应用地址类型 Uuid uuid; // UUID过滤条件 Uuid uuid_mask; // UUID掩码 std::vector<uint8_t> name; // 设备名过滤 uint16_t company; // 公司标识符 uint16_t company_mask; // 公司标识符掩码 uint8_t org_id; // 组织标识符 uint8_t tds_flags; // TDS标志 uint8_t tds_flags_mask; // TDS标志掩码 ApcfMetaDataType meta_data_type; // 元数据类型 std::vector<uint8_t> meta_data; // 元数据 uint8_t ad_type; // 广告类型 std::vector<uint8_t> data; // 数据 std::vector<uint8_t> data_mask; // 数据掩码 std::array<uint8_t, 16> irk; // 身份解析密钥 }; // 广告过滤器参数结构体 class AdvertisingFilterParameter { public: uint16_t feature_selection; // 功能选择 uint16_t list_logic_type; // 列表逻辑类型 uint8_t filter_logic_type; // 过滤器逻辑类型 uint8_t rssi_high_thresh; // RSSI高阈值 DeliveryMode delivery_mode; // 传输模式 uint16_t onfound_timeout; // 发现超时 uint8_t onfound_timeout_cnt; // 发现超时计数 uint8_t rssi_low_thresh; // RSSI低阈值 uint16_t onlost_timeout; // 丢失超时 uint16_t num_of_tracking_entries; // 追踪条目数 }; } // namespace hci } // namespace bluetooth

定义了GD蓝牙栈中HCI层的扫描回调接口和数据结构,是底层蓝牙芯片与上层协议栈之间的接口规范,提供了从BLE基础扫描到蓝牙5.x扩展功能的完整事件回调机制。

关键区别(与Legacy栈ble_scanner.h相比):地址类型:使用hci::Address而非RawAddress回调接口:更细粒度的HCI事件,如OnFilterEnableOnFilterParamSetup结构体设计:增加了AdvertisingPacketContentFilterCommand等HCI命令级别的数据结构

RegisterCallbacks

packages/modules/Bluetooth/system/main/shim/le_scanning_manager.cc // 注册扫描回调到shim层(关键桥接函数) void BleScannerInterfaceImpl::RegisterCallbacks(ScanningCallbacks* callbacks) { log::info("in shim layer"); scanning_callbacks_ = callbacks; // 保存上层回调指针,用于转发HCI事件到JNI层 } // 头文件中定义的成员变量(默认指向全局默认回调) ::ScanningCallbacks* scanning_callbacks_ = default_scanning_callback; // 回调指针,初始指向默认回调

BLE扫描回调的注册机制,是Gd蓝牙栈(新架构)与Legacy蓝牙栈(旧架构)之间的关键桥接点。

1. RegisterCallbacks()函数:这是回调注册的入口点,由上层(JNI层)调用接收ScanningCallbacks*指针参数,这是Legacy栈定义的回调接口将指针保存到scanning_callbacks_成员变量中,建立回调链

2. scanning_callbacks_成员变量:初始化为default_scanning_callback(全局默认回调指针)这是一个关键的双向绑定:Gd栈的HCI事件 → Shim层 → Legacy栈回调 → JNI层通过这个指针,Shim层能将底层HCI事件转发到上层Java应用

3. 注意事项:需要在启动扫描前调用RegisterCallbacks(),否则事件无法传递线程安全性需要考虑,回调调用发生在哪个线程

工作流程:

Gd蓝牙栈(HCI层) ↓ 产生扫描事件(如OnScanResult) ↓ 调用BleScannerInterfaceImpl::OnScanResult() Shim层(BleScannerInterfaceImpl) ↓ 处理/转换数据格式 ↓ 调用scanning_callbacks_->OnScanResult() Legacy栈回调(ScanningCallbacks实现) ↓ 转发到JNI层 ↓ 最终到达Java应用

三、 BLE扫描启动步骤(Native层接口)

Android启动BLE扫描的流程分为6个核心步骤(含必选前置初始化、核心启动、可选配置、事件回调),步骤按实际执行先后排序。

(1)步骤1:【必选】BLE扫描Native层全局初始化(前置准备)

触发时机:上层Java层首次初始化BLE扫描功能时触发,是启动扫描的基础前提(无此步骤则扫描实例/回调均未初始化,无法启动扫描)。

核心作用:创建BLE扫描单例实例、注册JNI层扫描回调、绑定Java层回调对象、初始化GATT统一接口。

对应Native层调用的接口/函数

JNI层:scanInitializeNative—— 初始化入口,加锁保证线程安全;Shim层:bluetooth::shim::get_ble_scanner_instance()—— 懒加载创建BleScannerInterfaceImpl单例,全Native层唯一扫描实例;Shim层:BleScannerInterfaceImpl::RegisterCallbacks—— 向扫描实例注册JNI层的JniScanningCallbacks;BTIF层:btif_gatt_get_interface()—— 初始化全局btgattInterface,为其scanner字段赋值上述扫描单例,提供统一GATT扫描接口。

(2)步骤2:【必选】向蓝牙栈注册扫描器(获取扫描器ID)

触发时机:初始化完成后,启动扫描前必须执行,是蓝牙栈识别扫描请求的前提。

核心作用:向蓝牙底层栈注册当前应用的扫描器,获取唯一的scanner_id,后续所有扫描操作(配置参数、启动/停止)均关联此ID。

对应Native层调用的接口/函数

核心接口:BleScannerInterface::RegisterScannerble_scanner.h,纯虚函数)—— 上层定义的扫描器注册标准接口;实现层:BleScannerInterfaceImpl::RegisterScannerble_scanner_interface_impl.h)—— Shim层具体实现,对接HCI层注册逻辑;回调触发:HCI层ScanningCallback::OnScannerRegisteredle_scanning_callback.h)—— 注册完成后底层回调,返回scanner_id和注册状态。

(3)步骤3:【必选】配置BLE扫描参数(指定扫描规则)

触发时机:扫描器注册成功后,启动扫描前执行(无参数则使用蓝牙栈默认参数,实际开发中均会自定义)。

核心作用:设置扫描的核心规则,包括扫描类型、扫描间隔/窗口、PHY物理层、1M/编码PHY对应的扫描器ID等。

对应Native层调用的接口/函数

核心接口:BleScannerInterface::SetScanParametersble_scanner.h,纯虚函数)—— 上层定义的参数配置标准接口;实现层:BleScannerInterfaceImpl::SetScanParametersble_scanner_interface_impl.h)—— Shim层具体实现,向下层HCI层传递扫描参数;回调触发:HCI层ScanningCallback::OnSetScannerParameterCompletele_scanning_callback.h)—— 参数配置完成后底层回调,返回配置状态。

(4)步骤4:【可选】配置并启用扫描过滤器(按需过滤设备)

触发时机:扫描参数配置完成后,启动扫描前(无过滤需求则直接跳过此步骤)。

核心作用:设置扫描过滤规则(如按设备地址、UUID、广播数据过滤),减少无效扫描结果,降低系统开销。

对应Native层调用的接口/函数(均来自BleScannerInterface,由BleScannerInterfaceImpl实现):

ScanFilterParamSetup:初始化扫描过滤器参数(如过滤索引、过滤逻辑);ScanFilterAdd:向指定过滤索引添加具体过滤规则(如UUID过滤、地址过滤);ScanFilterEnable:启用/禁用扫描过滤器功能;回调触发:HCI层OnFilterParamSetup/OnFilterConfigCallback/OnFilterEnable—— 过滤器配置/启用完成后底层回调,返回执行状态。

(5)步骤5:【核心】发送启动扫描指令(实际触发底层扫描)

触发时机:上述必选步骤完成后(可选过滤步骤按需完成),上层Java层调用startScan时触发。

核心作用:向蓝牙底层HCI层发送启动BLE扫描的指令,触发硬件实际执行BLE广播包的扫描逻辑。

对应Native层调用的接口/函数

核心接口:BleScannerInterface::Scanble_scanner.h,纯虚函数)—— 传入true表示启动扫描(传入false为停止);实现层:BleScannerInterfaceImpl::Scanble_scanner_interface_impl.h)—— Shim层具体实现,向下层HCI层发送启动扫描的底层指令,是启动扫描的核心调用

(6)步骤6:【必选】底层扫描结果回调(上层接收扫描数据)

触发时机:底层成功启动扫描后,检测到BLE设备广播包时持续触发。

核心作用:将蓝牙底层扫描到的设备信息(地址、信号强度、广播数据等)向上层传递,最终到Java层供业务使用。

对应Native层调用的接口/函数

HCI层触发:ScanningCallback::OnScanResultle_scanning_callback.h)—— 底层检测到广播包后,调用Shim层实现的此回调;Shim层分发:BleScannerInterfaceImpl::scanning_callbacks_ble_scanner_interface_impl.h)—— 通过步骤1注册的JniScanningCallbacks,将OnScanResult事件分发到JNI层;JNI层转发:JNI层将Native层的扫描结果转换为Java对象,调用步骤1中mScanCallbacksObj绑定的Java层回调方法,完成最终的结果传递。

数据流向

硬件事件 → HCI层 → ScanningCallback::OnScanResult()→ BleScannerInterfaceImpl::on_scan_result()→ JNI回调 → Java层
  1. 必选/可选界定:步骤1、2、3、5、6为启动扫描的必选步骤,步骤4为可选步骤(无过滤需求可直接跳过);
  2. 核心入口/核心调用scanInitializeNative初始化入口BleScannerInterface::Scan(true)启动扫描的核心调用
  3. 层间衔接核心BleScannerInterfaceImpl是所有步骤的核心载体,所有上层调用的接口最终均由其实现,所有底层回调均由其接收并分发。

四、关键Native接口汇总

核心管理接口

接口所在文件功能描述
scanInitializeNative()com_android_bluetooth_gatt.cpp扫描器初始化和回调注册
get_ble_scanner_instance()btif_ble_scanner.cc获取扫描器单例实例
bluetooth::shim::get_ble_scanner_instance()le_scanning_manager.cc创建/返回扫描器实现

BleScannerInterface接口 :

接口功能调用时机
RegisterScanner()注册扫描器,分配ID应用首次使用扫描时
Unregister()注销扫描器应用停止使用扫描时
Scan()开始/停止扫描每次扫描启停时
SetScanParameters()设置扫描参数扫描前或动态调整时
ScanFilterParamSetup()配置过滤参数需要过滤时
ScanFilterAdd()添加过滤条件需要特定设备时
ScanFilterClear()清除过滤条件切换过滤条件时
ScanFilterEnable()启用/禁用过滤过滤开关时

高级功能接口

接口功能备注
BatchscanConfigStorage()批量扫描存储配置批量扫描场景
BatchscanEnable()启用批量扫描低功耗扫描
StartSync()启动定期同步扩展广播
StopSync()停止同步资源释放
MsftAdvMonitorAdd()添加MSFT监控器Windows特有功能

五、时序图


六、测试

问题:Android 蓝牙 BLE 扫描 Native 层中,GD Shim 层的核心作用是什么?请结合上述代码具体说明。(高通 2024 蓝牙开发工程师校招真题)

答案

GD Shim 层是 Android 蓝牙新架构(GD)与传统蓝牙 Native 架构的桥接层,解决新老架构的兼容与接口适配问题;具体体现在:

  1. 提供get_ble_scanner_instance等统一的实例获取接口,对上层 BTIF/JNI 层屏蔽 GD 架构的实现细节;

  2. 核心类BleScannerInterfaceImpl同时实现传统架构的BleScannerInterface和 GD 架构 HCI 层的ScanningCallback,承上处理上层的扫描接口调用(如 Scan、RegisterScanner),启下重写并处理 GD 架构的底层扫描事件;

  3. 对上层暴露传统架构的标准接口,对下层对接 GD 架构的 HCI 扫描逻辑,实现新老架构的无缝衔接。

问题:上述代码中scanInitializeNative函数的核心执行逻辑是什么?为何要使用NewGlobalRef管理mScanCallbacksObj对象?(联发科 2023 蓝牙中间件开发社招真题)

答案

1. 核心执行逻辑

  ① 通过std::unique_lock加锁保证线程安全;

  ② 调用 Shim 层接口获取 BLE 扫描单例实例;

  ③ 向扫描实例注册 JNI 层的扫描回调JniScanningCallbacks

  ④ 清理旧的mScanCallbacksObj全局引用并创建新的全局引用,绑定 Java 层回调对象。

2. 使用NewGlobalRef的原因mScanCallbacksObj是 Java 层对象的 JNI 引用,若使用局部引用会在函数执行结束后被 JNI 自动释放,导致后续扫描回调无法找到 Java 层对象;全局引用会持续存在直到主动调用DeleteGlobalRef,能保证跨函数、跨线程的 Java 回调对象有效性,满足 BLE 扫描异步回调的需求。

问题BleScannerInterfaceImpl作为 BLE 扫描 Native 层的核心类,它实现 / 重写了哪些关键接口?分别承担什么职责?

答案

该类实现了 2 套核心接口,职责分工明确:

1. 实现传统架构的上层抽象接口BleScannerInterface(来自 ble_scanner.h),重写了 RegisterScanner、Scan、SetScanParameters 等所有纯虚函数,承担对接上层 BTIF/JNI 层,处理所有扫描相关的接口调用的职责,为上层提供标准的 BLE 扫描操作接口;

2. 重写GD 架构 HCI 层的ScanningCallback(来自 le_scanning_callback.h),实现了 OnScanResult、OnScannerRegistered、OnPeriodicSyncStarted 等所有虚函数,承担对接下层 HCI 层,接收并处理所有底层蓝牙扫描事件的职责;同时该类会将 HCI 层的扫描事件通过注册的ScanningCallbacks分发到上层,完成 “底层事件 - 上层回调” 的传递。

问题:Android蓝牙BLE扫描初始化流程中,scanInitializeNative函数的主要作用是什么?(2023年Android Framework面试真题)

答案:

scanInitializeNative是JNI层的入口函数,主要负责:

  ①获取BLE扫描器单例实例;

  ②注册JNI回调对象到Native层;

  ③清理旧的全局引用并创建新的全局引用。

该函数通过callbacks_mutex保证线程安全,是Java层与Native层扫描功能的桥梁。

问题:BleScannerInterfaceScanningCallback在BLE扫描架构中的角色区别是什么?(2022年蓝牙模块开发面试题)

答案:

BleScannerInterface是操作接口,定义了扫描器所有的控制方法(如开始扫描、设置参数等),采用命令模式向上层提供统一API。ScanningCallback是事件回调接口,定义扫描结果如何从底层上报到上层,采用观察者模式。两者共同构成BLE扫描的完整交互模型。

问题:分析BleScannerInterfaceImpl如何实现新旧蓝牙架构的兼容?(Android蓝牙模块重构技术讨论)

答案:

通过双重接口实现和适配器模式:

  ①实现旧的BleScannerInterface接口保持向后兼容;

  ②实现GD新架构的hci::ScanningCallback接口连接新HCI层;

  ③在内部通过parse_filter_command等方法进行协议转换;

  ④维护address_cache_处理地址去重等传统功能。

问题:请描述Android蓝牙LE扫描初始化过程中,回调接口是如何从Java层传递到底层HCI层的?

答案

回调传递通过多层接口实现:Java层通过JNI的mScanCallbacksObj保存回调对象;JNI层注册JniScanningCallbacksBleScannerInterfaceImplBleScannerInterfaceImpl同时实现BleScannerInterfacehci::ScanningCallback接口,形成双向回调链。

事件流向为:HCI事件→ScanningCallbackBleScannerInterfaceJniScanningCallbacks→JNI→Java。

问题:为什么在scanInitializeNative中需要使用std::shared_mutex?这种锁机制有什么优势? (Android系统性能优化面试题)

答案

std::shared_mutex(读写锁)允许多个读操作并发,但写操作独占。在蓝牙扫描场景中,回调注册是低频写操作,而扫描事件回调是高频读操作。这种设计提高了并发性能,避免了大量扫描事件回调时的锁竞争。

问题:BleScannerInterfaceImpl为何要同时继承BleScannerInterfacehci::ScanningCallback?这种设计模式是什么? (Google Bluetooth团队系统设计面试真题)

答案

这是适配器模式(Adapter Pattern)和桥接模式(Bridge Pattern)的结合。BleScannerInterfaceImpl作为适配器,将新的GD HCI接口适配到旧的BleScannerInterface接口;同时作为桥接,分离抽象(接口定义)与实现(HCI操作)。这种设计保持向后兼容,同时支持新架构。


七、log关键字

scanInitializeNative|get_ble_scanner_instance|RegisterCallbacks|OnScannerRegistered|BleScannerInterfaceImpl|ScanningCallback|scanning_callbacks_|bt_le_scanner_instance

Read more

分布式配置中心终极对决 Spring Cloud Config与Apollo架构深度解析

分布式配置中心终极对决 Spring Cloud Config与Apollo架构深度解析

作为有多年Java经验的开发者,我见证了配置管理从硬编码到配置中心的演进历程。记得曾有个项目,因为一个数据库配置错误,导致生产环境瘫痪2小时——没有靠谱的配置中心,就是在悬崖边跳舞。 目录 ✨ 摘要 1. 配置中心:微服务的"神经中枢" 1.1 为什么传统配置管理会要命? 1.2 配置中心的核心价值 2. Spring Cloud Config架构深度解析 2.1 核心架构设计 2.2 实时推送机制剖析 3. Apollo架构深度解析 3.1 核心架构设计 3.2 实时推送机制深度剖析 4. 核心特性对比分析 4.1 实时性对比 4.2 配置管理能力对比 5. 生产环境实战指南 5.

By Ne0inhk
免疫治疗门诊动线优化:Go离散事件仿真(DES)从“常规排队”到“ResusBay挤兑”的技术全解(上)

免疫治疗门诊动线优化:Go离散事件仿真(DES)从“常规排队”到“ResusBay挤兑”的技术全解(上)

面向读者:算法/后端/数据工程/运筹优化/医疗信息化 关键词:离散事件仿真(DES)、队列系统、资源竞争、预约模板、药房预配、irAE、抢救床位(ResusBay)、尾部风险(P90/超时率)、Go 免疫检查点抑制剂(ICI)是临床上的重大进展,但在医院运营视角下,它把输注中心变成了一个典型的复杂系统: 随机到达 + 随机服务时长 + 多站点串联 + 多资源并发 + 低概率高冲击风险事件(irAE)。 如果你只靠经验改流程,常常会陷入“改了这里堵了那里”;而工程上更稳的方法,是用 **离散事件仿真(DES)**在虚拟世界里“跑一天、一周、一年”,对比策略组合,找出瓶颈与最优干预点。 这篇文章从零到一搭建一个“可跑”的 Go DES 仿真框架,

By Ne0inhk
Spring Cloud Alibaba 2026 最新实战手册

Spring Cloud Alibaba 2026 最新实战手册

✨道路是曲折的,前途是光明的! 📝 专注C/C++、Linux编程与人工智能领域,分享学习笔记! 🌟 感谢各位小伙伴的长期陪伴与支持,欢迎文末添加好友一起交流! 📚 目录 * 一、引言:微服务架构的新篇章 * 二、Spring Cloud Alibaba 核心架构 * 三、环境搭建与项目初始化 * 四、核心组件实战 * 五、微服务治理最佳实践 * 六、性能优化与监控 * 七、总结与展望 一、引言:微服务架构的新篇章 1.1 为什么选择 Spring Cloud Alibaba? 在云原生时代,微服务架构已成为企业级应用的主流选择。Spring Cloud Alibaba 作为国内领先的微服务解决方案,凭借以下优势脱颖而出: Spring Cloud Alibaba 优势 生态完善 中文文档丰富 阿里生产验证

By Ne0inhk
openclaw新手入门指南:一文看懂环境搭建、模型配置与 WebUI 远程访问

openclaw新手入门指南:一文看懂环境搭建、模型配置与 WebUI 远程访问

目录 * 1. 基础设施层:OpenClaw 运行环境的初始化 * 2. 算力与模型层:蓝耘 MaaS 平台的接入配置 * 2.1 协议适配与 JSON 配置 * 3. 编排层:OpenClaw 初始化与 Onboarding 流程 * 3.1 模式选择与基础设置 * 3.2 模型提供商与应用集成策略 * 3.3 技能库(Skills)装载与服务启动 * 4. 网络架构与网关(Gateway)配置 * 4.1 网关暴露与安全策略 * 4.2 Web UI 远程访问与设备配对(Device Pairing) * 5. 高级模型编排与 JSON 配置深度解析

By Ne0inhk