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

Elasticsearch核心概念与Java客户端实战 构建高性能搜索服务

Elasticsearch核心概念与Java客户端实战 构建高性能搜索服务

目录 🎯 先说说我被ES"虐惨"的经历 ✨ 摘要 1. 为什么选择Elasticsearch? 1.1 从数据库的痛苦说起 1.2 Elasticsearch的优势 2. ES核心架构解析 2.1 集群架构 2.2 索引与分片 3. Java客户端实战 3.1 客户端选型对比 3.2 RestHighLevelClient配置 3.3 Spring Data Elasticsearch配置 4. 索引设计最佳实践 4.1 索引生命周期管理 4.2 映射设计技巧 5. 查询优化实战 5.1 查询类型对比 5.

By Ne0inhk
Java 大视界 -- Java 大数据在智能教育学习成果评估体系完善与教育质量提升中的深度应用(434)

Java 大视界 -- Java 大数据在智能教育学习成果评估体系完善与教育质量提升中的深度应用(434)

Java 大视界 -- Java 大数据在智能教育学习成果评估体系完善与教育质量提升中的深度应用(434) * 引言: * 正文: * 一、Java 大数据赋能智能教育评估的核心逻辑 * 1.1 教育评估数据特性与 Java 技术栈的精准适配 * 1.1.1 核心价值:从 “经验驱动” 到 “数据驱动” 的范式跃迁 * 1.2 数据流转与评估建模的底层逻辑 * 二、核心技术架构与落地路径(可直接复用) * 2.1 分层解耦的高可用架构设计 * 2.1.1 采集层:高并发多端数据接入(Java + Kafka) * 2.1.2 处理层:Spark + Hive 实现海量数据清洗与建模 * 2.1.

By Ne0inhk
华为OD机试双机位C卷真题:自动化维修流水线(C/C++/Java/Python/Go/JS)

华为OD机试双机位C卷真题:自动化维修流水线(C/C++/Java/Python/Go/JS)

自动化维修流水线 华为OD机试双机位C卷 - 华为OD上机考试双机位C卷 100分题型 华为OD机试双机位C卷真题目录点击查看: 华为OD机试双机位C卷真题题库目录|机考题库 + 算法考点详解 题目描述 小伙伴反馈题目大意:给定m条流水线,流水线可并行处理维修任务,给出n个任务,并给出每个任务的执行时间,要求完成所有任务的最短时间。 输入描述 第一行输入 任务数n和流水线数量m,用空格分割 第二行输入 每个任务完成所用时间 输出描述 输出最短执行完成所有任务数量 用例1 输入 10 1 10 20 30 5 5 5 5 10 5 10 输出 105 题解 思路:二分 + 递归回溯

By Ne0inhk

2026年人工智能发展趋势:效率重构、生态协同与规范前行

进入2026年,人工智能产业告别了对参数规模的盲目追逐,迈入“技术提质、产业落地、治理完善”的三重迭代期。技术层面,大模型向高效化演进、小模型实现场景突围,智能体能力持续升级;产业层面,AI与实体经济深度融合,从辅助工具向核心生产力转变;治理层面,全球监管规则加速落地,安全与合规成为行业发展的前置条件。本文结合真实案例与权威数据,拆解2026年人工智能的核心发展趋势,呈现技术变革与产业实践的真实图景。 趋势一:范式转移,小模型崛起重构AI效率格局 2026年成为小模型发展的分水岭,AI行业从“规模崇拜”转向“效率优先”,核心驱动力源于大模型边际效益递减与能源成本高企的双重压力。国际能源署测算,2026年AI相关电力消耗将相当于日本全国用电量,粗放式的参数扩张模式已难以为继,而“密度定律”的普及推动行业转向精细化运营——通过技术优化让模型更“小”且能力更强,小模型不再是大模型的简化版,而是针对特定场景的高效解决方案。 小模型的突破集中在特定任务性能、成本控制与端侧部署三大维度。性能上,小模型在垂直领域已实现对前沿大模型的超越:微博自研的VibeThinker模型仅15亿参数,却在

By Ne0inhk