BLE batch scan流程

由于公司手机经常出现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(&param_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才会成功

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值