android4.3中引入了蓝牙低能耗le(low energy),相应的也有一些方法/类。不过代码里,并没有找到初始调用的地方。所以这里还是先只分析下bt普通的扫描流程(类似android 4.2),先贴出流程图

主要通过“扫描”的流程来分析下

BluetoothSettings.java::startScanning            ----packageLocalBluetoothAdapter.java::startScanning       ----packageBluetoothAdapter.java::startDiscovery            ----frameworkAdapterService.java::startDiscovery              ----packagecom_android_bluetooth_btservice_AdapterService.cpp::startDiscoveryNative -jni

从这里开始分析下用到的一些变量和结构体

首先看startDiscoveryNative方法:

  static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {                                                   ALOGV("%s:",__FUNCTION__); jboolean result = JNI_FALSE; if (!sBluetoothInterface) return result; int ret = sBluetoothInterface->start_discovery(); result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; return result; }

分析点: int ret = sBluetoothInterface->start_discovery();

----------------------------------------------------------------------------

sBluetoothInterface的来源

查看com_android_bluetooth_btservice_AdapterService.cpp所在目录的Android.mk文件,

......
LOCAL_SHARED_LIBRARIES := \libandroid_runtime \libnativehelper \libcutils \libutils \liblog \libhardware
......

libhardware是编译时用到的,一般都是在hardware目录中。然后可以在子目录libhardware下找到bluetooth.h。在bluetooth.h中定义了bt_interface_t结构体。继而寻找该结构体对象的创建位置。在external/bluetooth/bluedroid/btif/src/bluetooth.c文件中找到。如下所示:

static const bt_interface_t bluetoothInterface = {sizeof(bluetoothInterface),    init,enable,disable,cleanup,get_adapter_properties,   get_adapter_property,set_adapter_property,get_remote_device_properties,  get_remote_device_property,    set_remote_device_property,    get_remote_service_record,get_remote_services,start_discovery,cancel_discovery,create_bond,remove_bond,cancel_bond,pin_reply,ssp_reply,get_profile_interface,dut_mode_configure,dut_mode_send,
#if BLE_INCLUDED == TRUE le_test_mode #else NULL #endif };

sBluetoothInterface对象便是获得了bluetoothInterface对象。

接下来,打开蓝牙、扫描等功能就会通过sBluetoothInterface调用结构体中声明的相应方法了。

流程:settings界面发起,LocalBluetoothAdapter.java过渡,去framework的转转(BluetoothAdapter.java)后,回到packages的AdapterService.java,再走JNI,接着去external处理。

----------------------------------------------------------------------------

接下来,跟一遍star_discovery

1.已经找到JNI层startDiscoveryNative函数对应的start_discovery方法(bluetooth.c),分析之。

static int start_discovery(void)
{/* sanity check */ if (interface_ready() == FALSE) return BT_STATUS_NOT_READY; return btif_dm_start_discovery(); }

2.分析btif_dm_start_discovery方法(btif_dm.c)

bt_status_t btif_dm_start_discovery(void)
{tBTA_DM_INQ inq_params;tBTA_SERVICE_MASK services = 0;BTIF_TRACE_EVENT1("%s", __FUNCTION__); /* TODO: Do we need to handle multiple inquiries at the same time? */ /* Set inquiry params and call API */ #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) inq_params.mode = BTA_DM_GENERAL_INQUIRY|BTA_BLE_GENERAL_INQUIRY; #else inq_params.mode = BTA_DM_GENERAL_INQUIRY; #endif  inq_params.duration = BTIF_DM_DEFAULT_INQ_MAX_DURATION; inq_params.max_resps = BTIF_DM_DEFAULT_INQ_MAX_RESULTS; inq_params.report_dup = TRUE; inq_params.filter_type = BTA_DM_INQ_CLR; /* TODO: Filter device by BDA needs to be implemented here */ /* Will be enabled to TRUE once inquiry busy level has been received */ btif_dm_inquiry_in_progress = FALSE; /* find nearby devices */ //下面是关键语句 BTA_DmSearch(&inq_params, services, bte_search_devices_evt); return BT_STATUS_SUCCESS;

(1) BTA_DmSearch分析

void BTA_DmSearch(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK services, tBTA_DM_SEARCH_CBACK *p_cback)
{tBTA_DM_API_SEARCH    *p_msg;  if ((p_msg = (tBTA_DM_API_SEARCH *) GKI_getbuf(sizeof(tBTA_DM_API_SEARCH))) != NULL) { memset(p_msg, 0, sizeof(tBTA_DM_API_SEARCH)); p_msg->hdr.event = BTA_DM_API_SEARCH_EVT; memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ)); p_msg->services = services; p_msg->p_cback = p_cback; p_msg->rs_res = BTA_DM_RS_NONE; bta_sys_sendmsg(p_msg); } }

看来只是发出一个消息,传递参数值。

(2)bte_search_devices_evt (btif_dm.c)

这条语句中,bte_search_devices_evt是真正用来搜索的,分析这个方法。贴出代码:

static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
{UINT16 param_len = 0; if (p_data) param_len += sizeof(tBTA_DM_SEARCH); /* Allocate buffer to hold the pointers (deep copy). The pointers will point to the end of the tBTA_DM_SEARCH */ switch (event) { case BTA_DM_INQ_RES_EVT: { if (p_data->inq_res.p_eir) param_len += HCI_EXT_INQ_RESPONSE_LEN; } break; case BTA_DM_DISC_RES_EVT: { if (p_data->disc_res.raw_data_size && p_data->disc_res.p_raw_data) param_len += p_data->disc_res.raw_data_size; } break; } BTIF_TRACE_DEBUG3("%s event=%s param_len=%d", __FUNCTION__, dump_dm_search_event(event), param_len); /* if remote name is available in EIR, set teh flag so that stack doesnt trigger RNR */ if (event == BTA_DM_INQ_RES_EVT) p_data->inq_res.remt_name_not_required = check_eir_remote_name(p_data, NULL, NULL); btif_transfer_context (btif_dm_search_devices_evt , (UINT16) event, (void *)p_data, param_len, (param_len > sizeof(tBTA_DM_SEARCH)) ? search_devices_copy_cb : NULL); }

看注释,这个方法作用就是Switches context from BTE to BTIF for DM search events,即将context从bte传给btif中的dm search事件。所以关键点在于btif_dm_search_devices_evt方法(btif_dm.c文件中定义),继续贴代码:

static void btif_dm_search_devices_evt (UINT16 event, char *p_param)
{switch (event) { case BTA_DM_INQ_RES_EVT: { /* inquiry result */ UINT32 cod; UINT8 *p_eir_remote_name = NULL; bt_bdname_t bdname; bt_bdaddr_t bdaddr; UINT8 remote_name_len; UINT8 *p_cached_name = NULL; tBTA_SERVICE_MASK services = 0; bdstr_t bdstr; p_search_data = (tBTA_DM_SEARCH *)p_param; //解析mac地址 bdcpy(bdaddr.address, p_search_data->inq_res.bd_addr); /* Callback to notify upper layer of device */ //下面是关键语句,回调方法  HAL_CBACK(bt_hal_cbacks, device_found_cb, num_properties, properties); } } break; ......

HAL_CBACK会注册回调方法,这里,会调用结构体对象bt_hal_cbacks中的device_found_cb方法。

继续扩展:

(a) bt_hal_cbacks对象分析   (根据初始化流程分析从头分析该bt_hal_cback对象的由来)

(a.1)首先,在AdapterService.java::onCreate方法中,有initNative方法。在相应JNI文件com_android_bluetooth_btservice_AdapterService.cpp中找到该方法,如下:

static bool initNative(JNIEnv* env, jobject obj) {ALOGV("%s:",__FUNCTION__); ...... if (sBluetoothInterface) { int ret = sBluetoothInterface->init(&sBluetoothCallbacks);   ...... }

(a.1.1)该JNI文件中定义了sBluetoothCallbacks,如下:

bt_callbacks_t sBluetoothCallbacks = {sizeof(sBluetoothCallbacks),   adapter_state_change_callback, adapter_properties_callback,   remote_device_properties_callback,device_found_callback,discovery_state_changed_callback,pin_request_callback,ssp_request_callback,bond_state_changed_callback,   acl_state_changed_callback,    callback_thread_event,dut_mode_recv_callback,le_test_mode_recv_callback
};

bt_callbacks_t结构体的定义在hardware/libhardware/include/hardware/bluetooth.h中,代码如下:

/** Bluetooth DM callback structure. */
typedef struct { /** set to sizeof(bt_callbacks_t) */ size_t size; adapter_state_changed_callback adapter_state_changed_cb; adapter_properties_callback adapter_properties_cb; remote_device_properties_callback remote_device_properties_cb; device_found_callback device_found_cb; discovery_state_changed_callback discovery_state_changed_cb; pin_request_callback pin_request_cb; ssp_request_callback ssp_request_cb; bond_state_changed_callback bond_state_changed_cb; acl_state_changed_callback acl_state_changed_cb; callback_thread_event thread_evt_cb; dut_mode_recv_callback dut_mode_recv_cb; le_test_mode_callback le_test_mode_cb; } bt_callbacks_t;

(a.1.2) 分析sBluetoothInterface对象的init方法。

因为sBluetoothInterface对象的值也是在bluetooth.c文件中定义的bluetoothInterface对象赋值的,所以直接找bluetoothInterface对象的定义处。

static const bt_interface_t bluetoothInterface = {sizeof(bluetoothInterface),    init,enable,disable,cleanup,get_adapter_properties,get_adapter_property,set_adapter_property,get_remote_device_properties,  get_remote_device_property,    set_remote_device_property,    get_remote_service_record,get_remote_services,start_discovery,cancel_discovery,create_bond,remove_bond,cancel_bond,pin_reply,ssp_reply,get_profile_interface,dut_mode_configure,dut_mode_send,
#if BLE_INCLUDED == TRUE le_test_mode #else NULL #endif };

在该结构体中找到init方法,然后继续在bluetooth.c中找init方法的定义。

static int init(bt_callbacks_t* callbacks )
{ALOGI("init"); /* sanity check */ if (interface_ready() == TRUE) return BT_STATUS_DONE; /* store reference to user callbacks */ bt_hal_cbacks = callbacks; //这里为bt_hal_cbacks对象赋值 /* add checks for individual callbacks ? */ bt_utils_init(); /* init btif */ btif_init_bluetooth(); return BT_STATUS_SUCCESS; }

通过上面标注的语句就知道了bt_hal_cback对象的由来,即sBluetoothCallbacks对象。

(b) HAL_CBACK分析

#define HAL_CBACK(P_CB, P_CBACK, ...)\if (P_CB && P_CB->P_CBACK) {            \BTIF_TRACE_API2("HAL %s->%s", #P_CB, #P_CBACK); \ P_CB->P_CBACK(__VA_ARGS__); \ } \ else { \ ASSERTC(0, "Callback is NULL", 0); \ }

这个宏主要就是执行了P_CB->P_CBACK(__VA_ARGS__); 在这里就是bt_hal_cback-> device_found_cb(...)方法。然后找到 sBluetoothCallbacks对象中对应的方法device_found_callback,继而找到该方法定义处。

static void device_found_callback(int num_properties, bt_property_t *properties) {......callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);   ......

JNI层的method_deviceFoundCallback函数对应java层的deviceFoundCallback方法,在JniCallbacks.java中。该类中又会调用RemoteDevice.java中的deviceFoundCallback方法。

然后,该回调方法中会发出广播,action为BluetoothDevice.ACTION_FOUND。这个广播会在BluetoothEventManager.java中处理。该类中通过addHandler方法,将action的值与相关handler接口类绑定。

接下来其他方法的处理,基本上也是这个套路。

总结下扫描的流程:

1.BluetoothEnabler类中调用startScanning方法,继而会调用LocalBluetoothAdapter,然后进入framework层,调用BluetoothAdapter中的startDiscovery方法,然后调用了AdapterService::startDiscovery(ps:在BluetoothAdapter类中,有mService和mMangerService对象,前一个代表AdapterService,后一个指BluetoothManagerService,比如enable BT的时候,就会调用BluetoothManagerService的方法,这个具体分析的时候要注意)。接着,会调用JNI层com_android_bluetooth_btservice_AdapterService.cpp中的startDiscoveryNative方法。

这个流程其实还是蛮清晰的,从上层应用执行到中间层再准备到协议栈external中去了。

下面就开始纠结了,各层跳来跳去:即external的分析

startDiscoveryNative (JNI层)
---> sBluetoothInterface->start_discovery() (bluetooth.c中)
---> btif_dm_start_discovery方法 (btif_dm.c)
---> BTA_DmSearch(&inq_params, services, bte_search_devices_evt);
---> bte_search_devices_evt
---> btif_dm_search_devices_evt
---> HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb,
                                 status, &bdaddr, 1, properties);
---> remote_device_properties_callback (JNI层)
--->callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr, types, props);
--> deviceFoundCallback (packages/apps/Bluetooth..JniCallbacks.java)
--> deviceFoundCallback (packages/apps/Bluetooth..RemoteDevices.java)
--->在RemoteDevices.java中会发出广播,action为BluetoothDevice.ACTION_FOUND。
--->广播接收者(packages/apps/Settings/..../BluetoothEventManager.java)
在其初始化方法中,为每个action绑定了一个名为XXHander的接口类,即以键值对形式保存。在广播的onReceive方法中,调用相应接口类处理。
--->调用dispatchDeviceAdded方法 (还是在BluetoothEventManager.java中)
ps:在这个方法中,会调用之前注册的回调类(这个回调类是DeviceListPreferenceFragment.java)的onDeviceAdded方法。
---> DeviceListPreferenceFragment.java::onDeviceAdded(还是在Settings模块中)
---> DeviceListPreferenceFragment.java::createDevicePreference方法

转载于:https://www.cnblogs.com/Free-Thinker/p/6418251.html

android4.3 Bluetooth分析之扫描分析相关推荐

  1. android4.3 Bluetooth(le)分析之startLeScan分析

    BluetoothAdapter.java中有low enery(le)的一些方法,android提供了这些方法,但源码中并未找到这些方法的调用之处.本文档主要分析这类方法的执行流程,来了解下le到底 ...

  2. 2.8.1利用“直流扫描分析”测试基本共射放大电路电压传输特性

    所谓电压传输特性,是指一个电路输出电压u.与输入电压u1之间的函数关系,即 f(u1),通常用曲线描述.电压传输特性是稳态特性,可用逐点测试的方法获得. 一.仿真电路 在Multisim电路图区域搭建 ...

  3. isis 网络 level 2 iih_ngspice实例介绍2--直流扫描分析

    前2篇文章介绍ngspice的安装,以及在直流工作点分析,这篇文章介绍直流扫描分析(DC sweep analysis),所谓直流扫描,是指某些电路参数(主要是电压源.电流源或者电阻器)的值在某一个范 ...

  4. ADS(Advanced Design system)谐波平衡分析(HarmonicBalance)和参数扫描分析(ParamSweep)

    前言 先进设计系统 Advanced Design system(ADS)Agilent Technologies 是领先的电子设计自动化软件,适用于射频.微波和信号完整性应用. 在一些情况下,当我们 ...

  5. 2.8.1 利用“直流扫描分析”测试基本共射放大电路电压传输特性

    所谓电压传输特性,是指一个电路输出电压uo与输人电压u1之间的函数关系,uo=f(u),通常用曲线描述.电压传输特性是稳态特性,可用逐点测试的方法获得. 一.仿真电路 在Multisim电路图区域搭建 ...

  6. 源代码扫描工具DMSCA(端玛科技企业级源代码安全和质量缺陷扫描分析服务平台)体验报告

    在开发过程中,优秀的源代码扫描工具可以帮助我们快速扫描漏洞,高效完成源代码缺陷修复.少漏报和误报率低的工具是我们的首选,我最近试用了许多源代码扫描工具和方案,其中 DMSCA(端玛科技企业级源代码安全 ...

  7. 3G入门之第三课 3G、WLAN、Bluetooth三者关系之分析

    第三课.3G.WLAN.Bluetooth三者关系之分析  一.背景  由于目前日本3G-FOMA商用情况和欧洲进行的3G试验并未取得人们预想的结果,导致各国运营商3G计划都进一步推迟:集团公司日前也 ...

  8. 常见的Web漏洞扫描分析工具

    常见的Web漏洞扫描分析工具: (1)Acunetix Web Vulnerability Scanner(简称awvs) 是一款知名的网络漏洞扫描工具,它通过网络爬虫测试你的网站安全,监测流行安全漏 ...

  9. 端口扫描分析(一)常用的网络相关命令

    发信人: Heway (陶陶), 信区: Internet_program 标  题: 端口扫描分析(一)常用的网络相关命令 发信站: 飘渺水云间 (Sun Mar 19 14:47:35 2000) ...

最新文章

  1. 我确实不知道如何使用计算机,【图片】从零开始的计算机教程:看不懂我就打死你【红石电路吧】_百度贴吧...
  2. 电脑粉碎文件 c语言,文件操作(二):文件粉碎机
  3. android java 时间测试方法_一个让你开挂的Android 性能测试方法
  4. leetcode268. 缺失数字
  5. linux文件系统选哪种,linux下几种文件系统的测试比较
  6. python连接sql引用的第三方库_python连接sqlserver数据库操作
  7. scp传输文件的命令
  8. 腾讯翻译君在线翻译怎么翻译整个文件_7款好用的英文翻译软件推荐
  9. 锐捷设备AC旁挂核心交换机①
  10. LaTex下载安装详解
  11. js实现网页在线聊天功能(一)
  12. android tv字体,android TV 屏幕适配 (一)
  13. 一个更Swifty核心动画
  14. Django-bootstrap3插件搭建Django+Bootstrap网站
  15. 树莓派-1、上手及资源
  16. 特征值和奇异值(svd)
  17. AI高效学习路径总结
  18. atof()函数实现
  19. STM8L051F3单片机竟然没有TIM1定时器,却有TIM2,3,4!!!害我调了一天没调出来
  20. 3分钟读懂RD与RT

热门文章

  1. uml学习之图书借阅简化用例图创建
  2. 电商人:别再跟数据透视表苦苦挣扎,这个报表神器才是你最后出路
  3. 数据体系建设的开端,该如何规划平台? 1
  4. 帆软报表插件开发之fine-decision中的LogInOutEventProvider扩展
  5. 计算机怎么调整显示英语翻译,翻译词汇:计算机显示英语词汇 口译词汇
  6. python多元回归 导出参数统计结果_如何从统计模型中WLS回归的二维参数得到检验的预测...
  7. 2010年6月计算机组织与结构,2010 计算机组织与体系结构课程设计.doc
  8. python爬虫之bs4库_三分钟搞定bs4库的解析器
  9. linux系统命令行方式复制文件
  10. linux 日志 转存,如何记录linux终端下的操作日志(转)