android Bluetooth进程获取mac地址流程分析

/ android / 没有评论 / 1566浏览

用到的代码文件

vendor/mediatek/proprietary/packages/apps/Bluetooth/:
src/com/android/bluetooth/btservice/AdapterService.java
src/com/android/bluetooth/btservice/AdapterProperties.java
jni/com_android_bluetooth_btservice_AdapterService.cpp

system/bt/:
btif/src/bluetooth.cc
btif/src/btif_core.cc
btif/src/btif_storage.cc
btif/include/btif_common.h
device/src/controller.cc

代码执行流程图

bluetooth mac 查看原图

蓝牙进程获取mac地址

下面的代码是以android O(api 27)为基础。

本文基于MTK(MediaTek)平台基线。

HCI: Host Controller Interface

MTK平台基线使用的是MTK自己的蓝牙app,所以蓝牙app的路径在mtk路径下。
大致看了一下,跟android官方的蓝牙app区别不是太大。

下面进入AdapterService.java类的onCreate()方法中。

@Override
public void onCreate() {
    super.onCreate();
    ......
    getAdapterPropertyNative(
        AbstractionLayer.BT_PROPERTY_BDADDR);
    ......
}

进入com_android_bluetooth_btservice_AdapterService.cpp的getAdapterPropertyNative()方法中。

static jboolean getAdapterPropertyNative(JNIEnv* env, 
    jobject obj, jint type) {
  ALOGV("%s", __func__);

  if (!sBluetoothInterface) return JNI_FALSE;

  int ret = sBluetoothInterface->get_adapter_property(
          (bt_property_type_t)type);
  return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

下面进入bluetooth.cc的get_adapter_property()方法中。

static int get_adapter_property(bt_property_type_t type) {
  /* sanity check */
  if (interface_ready() == false) return BT_STATUS_NOT_READY;

  return btif_get_adapter_property(type);
}

下面进入btif_core.cc的btif_get_adapter_property()方法中。
这个方法将我们的请求封装成一个request并在jni线程进行调用。

bt_status_t btif_get_adapter_property(
    bt_property_type_t type) {
  LOG_INFO(LOG_TAG, "method: %s entered, 
      type: %d", __func__,type);
  btif_storage_req_t req;

  BTIF_TRACE_EVENT("%s %d", __func__, type);

  /* Allow get_adapter_property only for BDADDR 
      and BDNAME if BT is disabled */
  if (!btif_is_enabled() && (type != BT_PROPERTY_BDADDR) &&
      (type != BT_PROPERTY_BDNAME))
    return BT_STATUS_NOT_READY;

  req.read_req.bd_addr = RawAddress::kEmpty;
  req.read_req.type = type;

  return btif_transfer_context(execute_storage_request,
                               BTIF_CORE_STORAGE_ADAPTER_READ, 
                               (char*)&req,
                               sizeof(btif_storage_req_t), 
                               NULL);
}

下面进入btif_core.cc文件的btif_transfer_context()方法。

bt_status_t btif_transfer_context(tBTIF_CBACK* p_cback, 
        uint16_t event,char* p_params, int param_len,
        tBTIF_COPY_CBACK* p_copy_cback) {
  LOG_INFO(LOG_TAG, "method: %s , p_cback pointer: %p ", 
      __func__,p_cback);

  tBTIF_CONTEXT_SWITCH_CBACK* p_msg = 
          (tBTIF_CONTEXT_SWITCH_CBACK*)osi_malloc(
      sizeof(tBTIF_CONTEXT_SWITCH_CBACK) + param_len);

  BTIF_TRACE_VERBOSE("btif_transfer_context event %d, len %d", 
          event,param_len);

  /* allocate and send message that will be 
      executed in btif context */
  /* internal event */
  p_msg->hdr.event = BT_EVT_CONTEXT_SWITCH_EVT; 
  p_msg->p_cb = p_cback;

  p_msg->event = event; /* callback event */

  /* check if caller has provided a copy callback 
     to do the deep copy */
  if (p_copy_cback) {
    p_copy_cback(event, p_msg->p_param, p_params);
  } else if (p_params) {
     /* callback parameter data */
    memcpy(p_msg->p_param, p_params, param_len);
  }

  btif_sendmsg(p_msg);

  return BT_STATUS_SUCCESS;
}

下面三个方法定义在btif_core.cc文件中。

void btif_sendmsg(void* p_msg) {
  LOG_INFO(LOG_TAG, "method %s ",__func__);
  do_in_jni_thread(base::Bind(&bt_jni_msg_ready, p_msg));
}


bt_status_t do_in_jni_thread(const base::Closure& task) {
  return do_in_jni_thread(FROM_HERE, task);
}


/**
 * This function posts a task into the btif message 
 * loop, that executes it in
 * the JNI message loop.
 **/
bt_status_t do_in_jni_thread(
        const tracked_objects::Location& from_here,
        const base::Closure& task) {
  if (!message_loop_ || !message_loop_->task_runner().get()) {
    BTIF_TRACE_WARNING("%s: Dropped message, "
            + "message_loop not initialized yet!",
            __func__);
    return BT_STATUS_FAIL;
  }

  if (message_loop_->task_runner()->PostTask(from_here, task))
    return BT_STATUS_SUCCESS;

  BTIF_TRACE_ERROR("%s: Post task to task "
          + "runner failed!", __func__);
  return BT_STATUS_FAIL;
}

从上面的方法可以看出将任务放在message_loop中进行执行。
jni具体执行某个任务的方法如下,该方法也定义在btif_core.cc文件中。

static void bt_jni_msg_ready(void* context) {
  LOG_INFO(LOG_TAG, "method %s ",__func__);
  BT_HDR* p_msg = (BT_HDR*)context;

  LOG_INFO(LOG_TAG,"btif task fetched event %x", 
          p_msg->event);

  switch (p_msg->event) {
    case BT_EVT_CONTEXT_SWITCH_EVT:
      btif_context_switched(p_msg);
      break;
    default:
      LOG_INFO(LOG_TAG, "method: %s", __func__);
      BTIF_TRACE_ERROR("unhandled btif event (%d)", 
            p_msg->event & BT_EVT_MASK);
      break;
  }
  osi_free(p_msg);
}

下面进入btif_core.cc的btif_context_switched()方法中。
"p->p_cb"就是execute_storage_request()方法。

static void btif_context_switched(void* p_msg) {
  LOG_INFO(LOG_TAG, "method: %s ", __func__);
  BTIF_TRACE_VERBOSE("btif_context_switched");

  tBTIF_CONTEXT_SWITCH_CBACK* p = 
      (tBTIF_CONTEXT_SWITCH_CBACK*)p_msg;
  LOG_INFO(LOG_TAG, "p_cb pointer: %p", p->p_cb);

  /* each callback knows how to parse the data */
  if (p->p_cb) p->p_cb(p->event, p->p_param);
}

下面进入btif_core.cc的execute_storage_request()方法中。

static void execute_storage_request(uint16_t event, 
      char* p_param) {
  LOG_INFO(LOG_TAG, "method: %s entered", __func__);
  bt_status_t status = BT_STATUS_SUCCESS;

  switch (event) {
    case BTIF_CORE_STORAGE_ADAPTER_WRITE: {
      btif_storage_req_t* p_req = 
          (btif_storage_req_t*)p_param;
      bt_property_t* p_prop = 
          &(p_req->write_req.prop);
      BTIF_TRACE_EVENT("type: %d, len %d, 0x%x", 
          p_prop->type, p_prop->len,p_prop->val);

      status = btif_storage_set_adapter_property(p_prop);
      HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, 
          status, 1, p_prop);
    } break;

    /*
      * 进入这个case
      */
    case BTIF_CORE_STORAGE_ADAPTER_READ: {
      btif_storage_req_t* p_req = 
          (btif_storage_req_t*)p_param;
      char buf[512];
      bt_property_t prop;
      prop.type = p_req->read_req.type;
      prop.val = (void*)buf;
      prop.len = sizeof(buf);
      if (prop.type == BT_PROPERTY_LOCAL_LE_FEATURES) {
        tBTM_BLE_VSC_CB cmn_vsc_cb;
        bt_local_le_features_t local_le_features;

        /* 
         * LE features are not stored in storage. 
         * Should be retrived from stack
         */
        BTM_BleGetVendorCapabilities(&cmn_vsc_cb);
        local_le_features.local_privacy_enabled = 
                BTM_BleLocalPrivacyEnabled();

        prop.len = sizeof(bt_local_le_features_t);
        if (cmn_vsc_cb.filter_support == 1)
          local_le_features.max_adv_filter_supported = 
                  cmn_vsc_cb.max_filter;
        else
          local_le_features.max_adv_filter_supported = 0;
        local_le_features.max_adv_instance = 
            cmn_vsc_cb.adv_inst_max;
        local_le_features.max_irk_list_size = 
            cmn_vsc_cb.max_irk_list_sz;
        local_le_features.rpa_offload_supported = 
            cmn_vsc_cb.rpa_offloading;
        local_le_features.scan_result_storage_size =
            cmn_vsc_cb.tot_scan_results_strg;
        local_le_features.activity_energy_info_supported =
            cmn_vsc_cb.energy_support;
        local_le_features.version_supported = 
            cmn_vsc_cb.version_supported;
        local_le_features.total_trackable_advertisers =
            cmn_vsc_cb.total_trackable_advertisers;

        local_le_features.extended_scan_support =
            cmn_vsc_cb.extended_scan_support > 0;
        local_le_features.debug_logging_supported =
            cmn_vsc_cb.debug_logging_supported > 0;
        memcpy(prop.val, &local_le_features, prop.len);
      } else {
         /*
          * 进入这里
          */
        LOG_INFO(LOG_TAG, "get adapter property");
        status = btif_storage_get_adapter_property(&prop);
      }
      HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, 
          status, 1, &prop);
    } break;
    ......
}

下面进入btif_storage.cc文件的btif_storage_get_adapter_property()方法中。

bt_status_t btif_storage_get_adapter_property(
        bt_property_t* property) {
  LOG_ERROR(LOG_TAG, "method: %s", __func__);
  LOG_ERROR(LOG_TAG, "type: %d", property->type);
  /* Special handling for adapter 
   * address and BONDED_DEVICES 
   */
  /*
   * 进入这里
   */
  if (property->type == BT_PROPERTY_BDADDR) {
    RawAddress* bd_addr = (RawAddress*)property->val;
    /* Fetch the local BD ADDR */
    const controller_t* controller = 
        controller_get_interface();
    if (controller->get_is_ready() == false) {
      LOG_ERROR(LOG_TAG,"%s: Controller not ready! "
              + "Unable to return Bluetooth Address",
              __func__);
      *bd_addr = RawAddress::kEmpty;
      return BT_STATUS_FAIL;
    } else {
     //如果controller准备好了,就直接获取
      LOG_ERROR(LOG_TAG, "%s: Controller ready!", __func__);
      *bd_addr = *controller->get_address();
      LOG_ERROR(LOG_TAG, "bd_addr: %s",
          bd_addr->ToString().c_str());
    }
    property->len = RawAddress::kLength;
    return BT_STATUS_SUCCESS;
  } else if (property->type == 
      BT_PROPERTY_ADAPTER_BONDED_DEVICES) {
  ......
}

下面是controller.cc文件中的controller_get_interface()方法。

const controller_t* controller_get_interface() {
  LOG_INFO(LOG_TAG, "method: controller_get_interface");
  static bool loaded = false;
  if (!loaded) {
    LOG_INFO(LOG_TAG, "controller_t didn't loaded,"
        + "so start to init it.");
    loaded = true;

    hci = hci_layer_get_interface();
    packet_factory = hci_packet_factory_get_interface();
    packet_parser = hci_packet_parser_get_interface();
  }else{
      LOG_INFO(LOG_TAG, "controller_t has been loaded,"
          + " you can get it.");
  }
  LOG_ERROR(LOG_TAG, "(use one controller_t?)"
      + "controller_t pointer: %p bool flag: %p", 
      &interface,&loaded);
  return &interface;
}

进入controller.cc文件的get_address()方法。

static RawAddress address;

static const RawAddress* get_address(void) {
  CHECK(readable);
  return &address;
}

至此我们已经获得了bt的mac address,并将其保存在bt_property_t中。
下面回到execute_storage_request()方法中。

static void execute_storage_request(uint16_t event, 
        char* p_param) {
  ......
      } else {
        LOG_INFO(LOG_TAG, "get adapter property");
        status = btif_storage_get_adapter_property(&prop);
      }
      /*
        * 要开始执行这里了。
        */
      HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, 
          status, 1, &prop);
    } break;
  ......
}

下面看下HAL_CBACK这个宏定义。
这个宏定义在btif_common.h文件中。

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

根据宏定义可以知道,结下来调用bt_hal_cbacks中的adapter_properties_cb。
bt_hal_cbacks就是下面的sBluetoothCallbacks, 其定义在jni/com_android_bluetooth_btservice_AdapterService.cpp文件中。

static 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,  energy_info_recv_callback};

那adapter_properties_cb定义在哪里的呢?
答案是在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;
energy_info_callback energy_info_cb;
} bt_callbacks_t;

这下就明白了,当我们在HAL层获得了bt的mac,然后就 会回调adapter_properties_callback()方法。
adapter_properties_callback()方法定义 在jni/com_android_bluetooth_btservice_AdapterService.cpp文件中。

static void adapter_properties_callback(
    bt_status_t status, int num_properties,
    bt_property_t* properties) {
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

  ALOGV("%s: Status is: %d, Properties: %d", 
      __func__, status, num_properties);

  if (status != BT_STATUS_SUCCESS) {
    ALOGE("%s: Status %d is incorrect", __func__, status);
    return;
  }

  ScopedLocalRef<jbyteArray> val(
      sCallbackEnv.get(),
      (jbyteArray)sCallbackEnv->NewByteArray(num_properties));
  if (!val.get()) {
    ALOGE("%s: Error allocating byteArray", __func__);
    return;
  }

  ScopedLocalRef<jclass> mclass(sCallbackEnv.get(),
          sCallbackEnv->GetObjectClass(val.get()));

  /* (BT) Initialize the jobjectArray and jintArray 
   * here itself and send the
   * initialized array pointers alone to get_properties 
   */

  ScopedLocalRef<jobjectArray> props(
      sCallbackEnv.get(),
      sCallbackEnv->NewObjectArray(num_properties, 
            mclass.get(), NULL));
  if (!props.get()) {
    ALOGE("%s: Error allocating object Array for properties", 
            __func__);
    return;
  }

  ScopedLocalRef<jintArray> types(
      sCallbackEnv.get(), 
      (jintArray)sCallbackEnv->NewIntArray(num_properties));
  if (!types.get()) {
    ALOGE("%s: Error allocating int Array for values", 
        __func__);
    return;
  }

  jintArray typesPtr = types.get();
  jobjectArray propsPtr = props.get();
  if (get_properties(num_properties, properties, 
          &typesPtr, &propsPtr) < 0) {
    return;
  }

  sCallbackEnv->CallVoidMethod(sJniCallbacksObj,
                   method_adapterPropertyChangedCallback,
                   types.get(), props.get());
}

这里最终回调到了AdapterProperties.java类中的adapterPropertyChangedCallback()方法。
后续的Java framework流程以后再分析。

两点注意

关于这个流程有两个个需要注意的地方:

第一次获取失败

这一切是建立在jni线程和其message loop初始化完成以后的情况之下。
如果jni线程的message loop没有初始化完成那么就会输出下面的log。

//第一次获取bt mac
I bt_btif : method: get_adapter_property:
I bt_btif_core: method: btif_get_adapter_property, type: 2
E bt_stack_manager: method: stack_manager_get_interface 
E bt_stack_manager: method: ensure_manager_initialized 
E bt_stack_manager: thread management_thread is ready! so return!
I bt_btif_core: start -> btif_transfer_context
I bt_btif_core: method: btif_transfer_context , 
        p_cback pointer: 0x969eba0d 
I bt_btif_core: start -> btif_sendmsg in btif_transfer_context()
I bt_btif_core: method btif_sendmsg 
W bt_btif : do_in_jni_thread: Dropped message, 
        message_loop not initialized yet!
//jni线程message loop还没初始化好,扔掉这个消息

为什么会扔掉消息呢?因为在btif_core.cc文件的do_in_jni_thread()中有进行判断。

/**
 * This function posts a task into the btif message loop, 
 * that executes it in
 * the JNI message loop.
 **/
bt_status_t do_in_jni_thread(
    const tracked_objects::Location& from_here,
    const base::Closure& task) {
  /*
    * 如果message loop没有初始化完成就扔掉这个消息。
    */
  if (!message_loop_ || !message_loop_->task_runner().get()) {
    BTIF_TRACE_WARNING("%s: Dropped message, message_loop “
        + ”not initialized yet!", __func__);
    return BT_STATUS_FAIL;
  }

  if (message_loop_->task_runner()->PostTask(from_here, task))
    return BT_STATUS_SUCCESS;

  BTIF_TRACE_ERROR("%s: Post task to task runner failed!", 
      __func__);
  return BT_STATUS_FAIL;
}

这里又有一个疑问,当这个消息扔掉以后后面还会获取mac吗?会的,在我的log输出中,即使 第一次消息被扔掉了,但是在紧接着的后面中暂不知道是从哪里发的消息通知到jin线程又 获取bt的mac。至于是哪个地方发的暂不研究。

"module_wrapper"

在我们蓝牙打开的过程中会生成一个"module_wrapper"线程。

void module_start_up_callbacked_wrapper(
    const module_t* module,thread_t* callback_thread,
    thread_fn callback) {
  callbacked_wrapper_t* wrapper =(callbacked_wrapper_t*)
          osi_calloc(sizeof(callbacked_wrapper_t));

  wrapper->module = module;
  wrapper->lifecycle_thread = thread_new("module_wrapper");
  wrapper->callback_thread = callback_thread;
  wrapper->callback = callback;

  // Run the actual module start up
  thread_post(wrapper->lifecycle_thread, 
          run_wrapped_start_up, wrapper);
}

在生成的线程中会执行controller.cc文件的start_up()方法。
而这个start_up()方法会调用一系列的hci命令,从硬件中获取蓝牙的相关信息,其中就 包括我们蓝牙硬件的mac地址。

关于"module_wrapper"线程的生成过程以后在研究。