由于公司手机经常出现android.bluetooth.cts.BluetoothLeScanTest#testBatchScan测试项fail的问题,对BatchScan流程进行分析
M0466EF 08-18 15:09:07.059 23766 23813 D BtGatt.ScanManager: Starting BLE batch scan
M0466F0 08-18 15:09:07.059 23766 23813 D BtGatt.ScanManager: configuring batch scan storage, appIf 6
ScanManager.java
在ScanManager.java下面可以看到如上的log打印,主要关注里面加粗的两个调用,gattClientConfigBatchScanStorageNative,gattClientStartBatchScanNative
private void resetBatchScan(ScanClient client) {
int scannerId = client.scannerId;
BatchScanParams batchScanParams = getBatchScanParams();
// Stop batch if batch scan params changed and previous params is not null.
if (mBatchScanParms != null && (!mBatchScanParms.equals(batchScanParams))) {
if (DBG) {
Log.d(TAG, "stopping BLe Batch");
}
resetCountDownLatch();
gattClientStopBatchScanNative(scannerId);
waitForCallback();
// Clear pending results as it's illegal to config storage if there are still
// pending results.
flushBatchResults(scannerId);
}
// Start batch if batchScanParams changed and current params is not null.
if (batchScanParams != null && (!batchScanParams.equals(mBatchScanParms))) {
int notifyThreshold = 95;
if (DBG) {
Log.d(TAG, "Starting BLE batch scan");
}
int resultType = getResultType(batchScanParams);
int fullScanPercent = getFullScanStoragePercent(resultType);
resetCountDownLatch();
if (DBG) {
Log.d(TAG, "configuring batch scan storage, appIf " + client.scannerId);
}
gattClientConfigBatchScanStorageNative(client.scannerId, fullScanPercent,
100 - fullScanPercent, notifyThreshold);
waitForCallback();
resetCountDownLatch();
int scanInterval =
Utils.millsToUnit(getBatchScanIntervalMillis(batchScanParams.scanMode));
int scanWindow =
Utils.millsToUnit(getBatchScanWindowMillis(batchScanParams.scanMode));
gattClientStartBatchScanNative(scannerId, resultType, scanInterval, scanWindow, 0,
DISCARD_OLDEST_WHEN_BUFFER_FULL);
waitForCallback();
}
mBatchScanParms = batchScanParams;
setBatchAlarm();
}
gattClientConfigBatchScanStorageNative
首先进入gattClientConfigBatchScanStorageNative看看处理流程,这里是JNI调用,找到对应的
private native void gattClientConfigBatchScanStorageNative(int clientIf,
int maxFullReportsPercent, int maxTruncatedReportsPercent,
int notifyThresholdPercent);
在com_android_bluetooth_gatt.cpp里面找到gattClientConfigBatchScanStorageNative实现
static void gattClientConfigBatchScanStorageNative(
JNIEnv* env, jobject object, jint client_if, jint max_full_reports_percent,
jint max_trunc_reports_percent, jint notify_threshold_level_percent) {
if (!sGattIf) return;
sGattIf->scanner->BatchscanConfigStorage(
client_if, max_full_reports_percent, max_trunc_reports_percent,
notify_threshold_level_percent,
base::Bind(&batchscan_cfg_storage_cb, client_if));
}
这里调用了sGattIf->scanner->BatchscanConfigStorage并在里面绑定了batchscan_cfg_storage_cb的回调。
进入BatchscanConfigStorage,然后就到了btif_ble_scanner.cc 里面
void BatchscanConfigStorage(int client_if, int batch_scan_full_max,
int batch_scan_trunc_max,
int batch_scan_notify_threshold,
Callback cb) override {
do_in_main_thread(
FROM_HERE,
base::Bind(&BTM_BleSetStorageConfig, (uint8_t)batch_scan_full_max,
(uint8_t)batch_scan_trunc_max,
(uint8_t)batch_scan_notify_threshold,
jni_thread_wrapper(FROM_HERE, cb),
bta_batch_scan_threshold_cb, (tBTM_BLE_REF_VALUE)client_if));
}
这里通过BTM_BleSetStorageConfig函数指针跳转到方法,在这里来写存储配置参数,log打印
M0466F1 08-18 15:09:07.059 23766 23823 D bt_btm : BTM_BleGetVendorCapabilities
M0466F2 08-18 15:09:07.059 23766 23823 I bt_btm : BTM_BleSetStorageConfig: 0, 6, 100, 0, 95
/*******************************************************************************
*
* Description This function is called to write storage config params.
*
* Parameters: batch_scan_full_max - Max storage space (in %) allocated to
* full style
* batch_scan_trunc_max - Max storage space (in %) allocated to
* trunc style
* batch_scan_notify_threshold - Setup notification level based
* on total space
* cb - Setup callback pointer
* p_thres_cback - Threshold callback pointer
* ref_value - Reference value
*
******************************************************************************/
void BTM_BleSetStorageConfig(uint8_t batch_scan_full_max,
uint8_t batch_scan_trunc_max,
uint8_t batch_scan_notify_threshold,
Callback<void(uint8_t /* status */)> cb,
tBTM_BLE_SCAN_THRESHOLD_CBACK* p_thres_cback,
tBTM_BLE_REF_VALUE ref_value) {
if (!can_do_batch_scan()) { //这里面会打印BTM_BleGetVendorCapabilities
cb.Run(BTM_ERR_PROCESSING);
return;
}
BTM_TRACE_EVENT("%s: %d, %d, %d, %d, %d", __func__,
ble_batchscan_cb.cur_state, ref_value, batch_scan_full_max,
batch_scan_trunc_max, batch_scan_notify_threshold);
ble_batchscan_cb.p_thres_cback = p_thres_cback;
ble_batchscan_cb.ref_value = ref_value;
if (batch_scan_full_max > BTM_BLE_ADV_SCAN_FULL_MAX ||
batch_scan_trunc_max > BTM_BLE_ADV_SCAN_TRUNC_MAX ||
batch_scan_notify_threshold > BTM_BLE_ADV_SCAN_THR_MAX) {
BTM_TRACE_ERROR("Illegal set storage config params");
cb.Run(BTM_ILLEGAL_VALUE);
return;
}
if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state ||
BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state) {
btm_ble_enable_batchscan(Bind(&feat_enable_cb));
ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
}
btm_ble_set_storage_config(batch_scan_full_max, batch_scan_trunc_max,
batch_scan_notify_threshold,
Bind(&storage_config_cb, cb));
return;
}
主要关注btm_ble_enable_batchscan这个函数,这里如果执行成功返回结果,将回调到feat_enable_cb方法
/* This function enables the customer specific feature in controller */
void btm_ble_enable_batchscan(hci_cmd_cb cb) {
uint8_t len = BTM_BLE_BATCH_SCAN_ENB_DISB_LEN;
uint8_t param[len];
memset(param, 0, len);
uint8_t* p = param;
UINT8_TO_STREAM(p, BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE);
UINT8_TO_STREAM(p, 0x01 /* enable */);
btu_hcif_send_cmd_with_cb(FROM_HERE, HCI_BLE_BATCH_SCAN, param, len, cb);
}
到这里发送了HCI_BLE_BATCH_SCAN command之后,差不多就到了芯片那边去了,流程就跟到这里
/* Batch scan opcode */
#define HCI_BLE_BATCH_SCAN (0x0156 | HCI_GRP_VENDOR_SPECIFIC)
#define HCI_GRP_VENDOR_SPECIFIC (0x3F << 10) /* 0xFC00 */
我们来算一下这里的HCI_BLE_BATCH_SCAN 的 opcode,0x0156 或上 HCI_GRP_VENDOR_SPECIFIC,也就是 0x0156 或 0xfc00 = 0xfd56, 在hci log里面找到对应的opcode 0xfd56,就是这里发出的hci命令
gattClientStartBatchScanNative
然后进入gattClientStartBatchScanNative流程分析,同样是通过JNI调用
private native void gattClientStartBatchScanNative(int clientIf, int scanMode,
int scanIntervalUnit, int scanWindowUnit, int addressType, int discardRule);
进入com_android_bluetooth_gatt.cpp
static void gattClientStartBatchScanNative(JNIEnv* env, jobject object,
jint client_if, jint scan_mode,
jint scan_interval_unit,
jint scan_window_unit,
jint addr_type, jint discard_rule) {
if (!sGattIf) return;
sGattIf->scanner->BatchscanEnable(
scan_mode, scan_interval_unit, scan_window_unit, addr_type, discard_rule,
base::Bind(&batchscan_enable_cb, client_if));
}
这里面的参数就是一些扫描配置参数,scan_interval、scan_window、scan_mode等等,直接进入BatchscanEnable
void BatchscanEnable(int scan_mode, int scan_interval, int scan_window,
int addr_type, int discard_rule, Callback cb) override {
do_in_main_thread(
FROM_HERE, base::Bind(&BTM_BleEnableBatchScan, scan_mode, scan_interval,
scan_window, discard_rule, addr_type,
jni_thread_wrapper(FROM_HERE, cb)));
}
M046717 08-18 15:09:07.069 23766 23823 I bt_btm : BTM_BleEnableBatchScan: 2, 8000, 2400, 0, 0, 0
M046718 08-18 15:09:07.069 23766 23823 D bt_btm : BTM_BleGetVendorCapabilities
M046719 08-18 15:09:07.069 23766 23823 D bt_btm : BTM_BleEnableBatchScan: 2, 1f40, 960, 0, 2
/* This function is called to configure and enable batch scanning */
void BTM_BleEnableBatchScan(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
uint32_t scan_interval, uint32_t scan_window,
tBLE_ADDR_TYPE addr_type,
tBTM_BLE_DISCARD_RULE discard_rule,
Callback<void(uint8_t /* status */)> cb) {
BTM_TRACE_EVENT("%s: %d, %d, %d, %d, %d, %d", __func__, scan_mode,
scan_interval, scan_window, addr_type, discard_rule);
if (!can_do_batch_scan()) {
cb.Run(BTM_ERR_PROCESSING);
return;
}
BTM_TRACE_DEBUG("%s: %d, %x, %x, %d, %d", __func__, scan_mode, scan_interval,
scan_window, discard_rule, ble_batchscan_cb.cur_state);
/* Only 16 bits will be used for scan interval and scan window as per
* agreement with Google */
/* So the standard LE range would suffice for scan interval and scan window */
//验证参数合法性
if ((BTM_BLE_ISVALID_PARAM(scan_interval, BTM_BLE_SCAN_INT_MIN,
BTM_BLE_SCAN_INT_MAX) ||
BTM_BLE_ISVALID_PARAM(scan_window, BTM_BLE_SCAN_WIN_MIN,
BTM_BLE_SCAN_WIN_MAX)) &&
(BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode ||
BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode ||
BTM_BLE_BATCH_SCAN_MODE_PASS_ACTI == scan_mode) &&
(BTM_BLE_DISCARD_OLD_ITEMS == discard_rule ||
BTM_BLE_DISCARD_LOWER_RSSI_ITEMS == discard_rule)) {
} else {
BTM_TRACE_ERROR("%s: Illegal enable scan params", __func__);
cb.Run(BTM_ILLEGAL_VALUE);
return;
}
if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state ||
BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state) {
btm_ble_enable_batchscan(Bind(&feat_enable_cb));
ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
}
ble_batchscan_cb.scan_mode = scan_mode;
ble_batchscan_cb.scan_interval = scan_interval;
ble_batchscan_cb.scan_window = scan_window;
ble_batchscan_cb.addr_type = addr_type;
ble_batchscan_cb.discard_rule = discard_rule;
/* This command starts batch scanning, if enabled */
btm_ble_set_batchscan_param(scan_mode, scan_interval, scan_window, addr_type,
discard_rule, Bind(¶m_enable_cb, cb));
}
这里首先是btm_ble_enable_batchscan,也就是上面也走过的方法,进入之后发送command命令
/* This function enables the customer specific feature in controller */
void btm_ble_enable_batchscan(hci_cmd_cb cb) {
uint8_t len = BTM_BLE_BATCH_SCAN_ENB_DISB_LEN;
uint8_t param[len];
memset(param, 0, len);
uint8_t* p = param;
UINT8_TO_STREAM(p, BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE);
UINT8_TO_STREAM(p, 0x01 /* enable */);
btu_hcif_send_cmd_with_cb(FROM_HERE, HCI_BLE_BATCH_SCAN, param, len, cb);
}
然后就是btm_ble_set_batchscan_param,设置batchscan的参数
/* This function writes the batch scan params in controller */
void btm_ble_set_batchscan_param(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
uint32_t scan_interval, uint32_t scan_window,
tBLE_ADDR_TYPE addr_type,
tBTM_BLE_DISCARD_RULE discard_rule,
hci_cmd_cb cb) {
// Override param and decide addr_type based on own addr type
// TODO: Remove upper layer parameter?
addr_type = btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type;
uint8_t len = BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN;
uint8_t param[len];
memset(param, 0, len);
uint8_t* p = param;
UINT8_TO_STREAM(p, BTM_BLE_BATCH_SCAN_SET_PARAMS);
UINT8_TO_STREAM(p, scan_mode);
UINT32_TO_STREAM(p, scan_window);
UINT32_TO_STREAM(p, scan_interval);
UINT8_TO_STREAM(p, addr_type);
UINT8_TO_STREAM(p, discard_rule);
btu_hcif_send_cmd_with_cb(FROM_HERE, HCI_BLE_BATCH_SCAN, param, len, cb);
}
这个流程一共向芯片发送了三次HCI_BLE_BATCH_SCAN命令,有点点不理解为什么要三次
在结束扫描后,也会发送HCI_BLE_BATCH_SCAN命令获取扫描信息,里面的Number of records: 0这个就是cts失败的原因,要大于0才会成功