Bluetooth initialization - Bluetooth process Initialization - Native(Cpp)

1. Overview

AdapterService.java # onCreate() 调用 initNative() 初始化 Native 层。

2. initNative()

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

    @Override
    public void onCreate() {
...
        initNative(isGuest(), isNiapMode(), configCompareResult, isAtvDevice);
...
    }


 
    native boolean initNative(boolean startRestricted, boolean isNiapMode,
                              int configCompareResult, boolean isAtvDevice);

以上四个参数的值如下(Android R 上新增log,于 Pixel5 平台运行)


parameters log.png

BluetoothAdapterService: kt
guest=false, niapMode=false, configCompareResult=0, isAtvDevice=false

[packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp][com_android_bluetooth_btservice_AdapterService]

static bool initNative(JNIEnv* env, jobject obj, jboolean isGuest,
                       jboolean isNiapMode, int configCompareResult,
                       jboolean isAtvDevice) {

  android_bluetooth_UidTraffic.clazz =
      (jclass)env->NewGlobalRef(env->FindClass("android/bluetooth/UidTraffic"));

  sJniAdapterServiceObj = env->NewGlobalRef(obj);
  sJniCallbacksObj =
      env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));

  // 1
  int ret = sBluetoothInterface->init(
      &sBluetoothCallbacks, isGuest == JNI_TRUE ? 1 : 0,
      isNiapMode == JNI_TRUE ? 1 : 0, configCompareResult,
      isAtvDevice == JNI_TRUE ? 1 : 0);

  // 2
  ret = sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts);

  // 3
  sBluetoothSocketInterface =
      (btsock_interface_t*)sBluetoothInterface->get_profile_interface(
          BT_PROFILE_SOCKETS_ID);

  return JNI_TRUE;
}

注释 //1 处设置的回调函数列表如下:

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};

注释 //2 处设置的回调函数列表如下:

static bt_os_callouts_t sBluetoothOsCallouts = {
    sizeof(sBluetoothOsCallouts), set_wake_alarm_callout,
    acquire_wake_lock_callout, release_wake_lock_callout,
};

2.1 init bluetooth

分析以下源码实现

  int ret = sBluetoothInterface->init(
      &sBluetoothCallbacks, isGuest == JNI_TRUE ? 1 : 0,
      isNiapMode == JNI_TRUE ? 1 : 0, configCompareResult,
      isAtvDevice == JNI_TRUE ? 1 : 0);

参考 3.1 初始化 JNI 可知,执行 sBluetoothInterface->init ,相当于执行

system/bt/btif/src/bluetooth.cc

static int init(bt_callbacks_t* callbacks, bool start_restricted,
                bool is_niap_mode, int config_compare_result, bool is_atv) {
  // 如果初始化过,则不再初始化。
  if (interface_ready()) return BT_STATUS_DONE;

  bt_hal_cbacks = callbacks;                       // 1 缓存 JNI 设置的回调函数列表
  restricted_mode = start_restricted;
  niap_mode = is_niap_mode;
  niap_config_compare_result = config_compare_result;
  is_local_device_atv = is_atv;

  stack_manager_get_interface()->init_stack();    // 2
  btif_debug_init();                              // 3
  return BT_STATUS_SUCCESS;
}

下面详细分析以上代码注释的 1、2、3 三个部分。

2.1.1 缓存 JNI 设置的回调函数列表

system/bt/btif/src/bluetooth.cc

bt_callbacks_t* bt_hal_cbacks = NULL;

system/bt/include/hardware/bluetooth.h

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;

蓝牙协议栈可以通过 bluetooth.h 中定义的结构体成员,来回调 JNI 注册的回调函数。

2.1.2 初始化 stack_manager

2.1.2.1 stack_manager_get_interface()

system/bt/btif/src/stack_manager.cc

static const stack_manager_t interface = {init_stack, start_up_stack_async,
                                          shut_down_stack_async, clean_up_stack,
                                          get_stack_is_running};



const stack_manager_t* stack_manager_get_interface() {
  ensure_manager_initialized();
  return &interface;
}


static void ensure_manager_initialized() {
  // 如果已经初始化,则返回
  if (management_thread.IsRunning()) return;

  management_thread.StartUp();
}

stack_manager_get_interface() 干了两件事

  1. 启动了 stack_manager 的工作线程 management_thread
  2. 提供了外部访问的入口函数列表。

2.1.2.2 init_stack()

system/bt/btif/src/stack_manager.cc

static void init_stack() {
  // This is a synchronous process.
  semaphore_t* semaphore = semaphore_new(0);
  management_thread.DoInThread(FROM_HERE,
                               base::Bind(event_init_stack, semaphore));
  semaphore_wait(semaphore);
  semaphore_free(semaphore);
}



// Synchronous function to initialize the stack
static void event_init_stack(void* context) {
  semaphore_t* semaphore = (semaphore_t*)context;

  if (stack_is_initialized) {
......
  } else {
    module_management_start();   // 启动 module_management,实际未执行任何代码

    module_init(get_module(OSI_MODULE));
    module_init(get_module(BT_UTILS_MODULE));
    module_init(get_module(BTIF_CONFIG_MODULE));
    btif_init_bluetooth();

    stack_is_initialized = true;
  }
  if (semaphore) semaphore_post(semaphore);
}
2.1.2.2.1 初始化不同的 module

不同 module 初始化,参考 module_init

2.1.2.2.2 初始化蓝牙

system/bt/btif/src/btif_core.cc

bt_status_t btif_init_bluetooth() {
  exit_manager = new base::AtExitManager();

  bte_main_boot_entry();

  jni_thread.StartUp();
  jni_thread.DoInThread(FROM_HERE, base::Bind(btif_jni_associate));
  return BT_STATUS_SUCCESS;
}
  1. 创建 chrome 库中的 AtExitManager
  2. bte_main_boot_entry() ;
  3. 启动 jni_thread,并在 jni_thread 中执行 btif_jni_associate 。
2.1.2.2.2.1 AtExitManager

创建 AtExitManager 对象

2.1.2.2.2.2 初始化 BTE

system/bt/main/bte_main.cc

void bte_main_boot_entry(void) {
  module_init(get_module(INTEROP_MODULE));

  hci = hci_layer_get_interface();
  hci->set_data_cb(base::Bind(&post_to_main_message_loop));

  module_init(get_module(STACK_CONFIG_MODULE));
}

不同 module 初始化,参考 module_init

2.1.2.2.2.3 启动 jni thread,并执行指定函数
static void btif_jni_associate() {
  BTIF_TRACE_DEBUG("%s Associating thread to JVM", __func__);
  HAL_CBACK(bt_hal_cbacks, thread_evt_cb, ASSOCIATE_JVM);
}

根据前文可知,bt_hal_cbacks 缓存的是 JNI 注册下来的回调函数,因此这里会执行 JNI 中的 callback_thread_event 函数,具体实现如下。
[packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp][com_android_bluetooth_btservice_AdapterService]

static void callback_thread_event(bt_cb_thread_evt event) {
  if (event == ASSOCIATE_JVM) {
    JavaVMAttachArgs args;
    char name[] = "BT Service Callback Thread";
    args.version = JNI_VERSION_1_6;
    args.name = name;
    args.group = NULL;
    vm->AttachCurrentThread(&callbackEnv, &args);
    sHaveCallbackThread = true;
    sCallbackThread = pthread_self();
  } else if (event == DISASSOCIATE_JVM) {
......
  }
}

2.1.3 btif_debug_init() 实现

system/bt/btif/src/btif_debug.cc

void btif_debug_init(void) {
#if (BTSNOOP_MEM == TRUE)
  btif_debug_btsnoop_init();
#endif
}

debug相关的内容,暂不分析。

2.2 set_os_callouts

分析以下源码实现

  ret = sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts)

2.2.1 参数定义 - sBluetoothOsCallouts

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

static bt_os_callouts_t sBluetoothOsCallouts = {
    sizeof(sBluetoothOsCallouts), set_wake_alarm_callout,
    acquire_wake_lock_callout, release_wake_lock_callout,
};

具体实现暂不贴代码分析,至少是知道具体实现代码 JNI 中。

bt_os_callouts_t 原型定义
system/bt/include/hardware/bluetooth.h

typedef struct {
  /* set to sizeof(bt_os_callouts_t) */
  size_t size;

  set_wake_alarm_callout set_wake_alarm;
  acquire_wake_lock_callout acquire_wake_lock;
  release_wake_lock_callout release_wake_lock;
} bt_os_callouts_t;



typedef bool (*set_wake_alarm_callout)(uint64_t delay_millis, bool should_wake,
                                       alarm_cb cb, void* data);
typedef int (*acquire_wake_lock_callout)(const char* lock_name);
typedef int (*release_wake_lock_callout)(const char* lock_name);

2.2.2 函数实现 - set_os_callouts

同 2.1,执行 sBluetoothInterface->set_os_callouts 即为执行
system/bt/btif/src/bluetooth.cc

static int set_os_callouts(bt_os_callouts_t* callouts) {
  wakelock_os_callouts_saved = callouts;                   // 1
  wakelock_set_os_callouts(&wakelock_os_callouts_jni);     // 2
  return BT_STATUS_SUCCESS;
}



static bt_os_callouts_t* wakelock_os_callouts_saved = nullptr;
  1. 注释 // 1 是赋值语句,bluetooth.cc 拿到了 JNI 中具体实现的方法的入口,存在 wakelock_os_callouts_saved 变量中。
  2. 注释 // 2 是调用蓝牙协议栈中的 wakelock 有关的内容,将 JNI 的 wakelock 实现方法注入到 wakelock模块中。
  wakelock_set_os_callouts(&wakelock_os_callouts_jni); 

2.2.2.1 参数来源 - wakelock_os_callouts_jni

static bt_os_callouts_t wakelock_os_callouts_jni = {
    sizeof(wakelock_os_callouts_jni),
    nullptr /* not used */,
    acquire_wake_lock_cb,
    release_wake_lock_cb,
};



static int acquire_wake_lock_cb(const char* lock_name) {
  return do_in_jni_thread(
      FROM_HERE, base::Bind(base::IgnoreResult(
                                wakelock_os_callouts_saved->acquire_wake_lock),
                            lock_name));
}

static int release_wake_lock_cb(const char* lock_name) {
  return do_in_jni_thread(
      FROM_HERE, base::Bind(base::IgnoreResult(
                                wakelock_os_callouts_saved->release_wake_lock),
                            lock_name));

可以看到这里最终调用的 wakelock_os_callouts_saved 变量的内容,该变量在 2.2.2 中赋值,由 JNI 传递而来。

2.2.2.2 函数实现 - wakelock_set_os_callouts

system/bt/osi/src/wakelock.cc

void wakelock_set_os_callouts(bt_os_callouts_t* callouts) {
  wakelock_os_callouts = callouts;
  is_native = (wakelock_os_callouts == NULL);
  LOG_INFO(LOG_TAG, "%s set to %s", __func__,
           (is_native) ? "native" : "non-native");
}



static bt_status_t wakelock_acquire_callout(void) {
  return static_cast<bt_status_t>(
      wakelock_os_callouts->acquire_wake_lock(WAKE_LOCK_ID));
}



static bt_status_t wakelock_release_callout(void) {
  return static_cast<bt_status_t>(
      wakelock_os_callouts->release_wake_lock(WAKE_LOCK_ID));
}

2.2.3 小结

经过以上分析可知:

  1. 具体的 wakelock 实现方法在 JNI 中;
  2. wakelock 实现方法被传递到 bluetooth.cc 和 wakelock.cc 中供回调使用。

2.3 get_profile_interface

 sBluetoothSocketInterface =
      (btsock_interface_t*)sBluetoothInterface->get_profile_interface(
          BT_PROFILE_SOCKETS_ID);

system/bt/btif/src/bluetooth.cc

static const void* get_profile_interface(const char* profile_id) {
  if (is_profile(profile_id, BT_PROFILE_SOCKETS_ID))
    return btif_sock_get_interface();
......
}

system/bt/btif/src/btif_sock.cc

const btsock_interface_t* btif_sock_get_interface(void) {
  static btsock_interface_t interface = {
      sizeof(interface), btsock_listen, /* listen */
      btsock_connect,                   /* connect */
      btsock_request_max_tx_data_length /* request_max_tx_data_length */
  };

  return &interface;
}

由以上代码流程,JNI 获取到 SOCKET profile 的入口函数列表。
传递不同的 profile ID 即可获取到对应的 profile 的入口函数列表。

Android 12 之后增加了一个参数

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

        initNative(isGuest(), isCommonCriteriaMode(), configCompareResult, getInitFlags(),
                isAtvDevice);

getInitFlags() 中的 Flag 用于控制 GD 协议栈的 log
根据 device_config 数据库的配置来控制log的开启与否,目前全部开启的命令,开启之后,重启蓝牙。

adb shell device_config put bluetooth INIT_gd_core true
adb shell device_config put bluetooth INIT_gd_advertising true
adb shell device_config put bluetooth INIT_gd_scanning true
adb shell device_config put bluetooth INIT_gd_hci true
adb shell device_config put bluetooth INIT_gd_controller true
adb shell device_config put bluetooth INIT_gd_acl true
adb shell device_config put bluetooth INIT_gd_l2cap true
adb shell device_config put bluetooth INIT_gd_rust true
adb shell device_config put bluetooth INIT_gd_link_policy true

adb shell device_config put bluetooth INIT_btaa_hci true

// 未单独设置的tag,则使用 all 属性
adb shell device_config put bluetooth INIT_logging_debug_enabled_for_all true
// 单独关闭或开启log 的tag,优先级高于 all,低于单独设置
//adb shell device_config put bluetooth INIT_logging_debug_enabled_for_tags tags
//adb shell device_config put bluetooth INIT_logging_debug_disabled_for_tags tags

上面命令中的 bluetooth 是 name space

frameworks/base/core/java/android/provider/DeviceConfig.java

由下面这个类实现 device_config
[com_android_bluetooth_btservice_AdapterService]: https://cs.android.com/android/platform/superproject/+/android-11.0.0_r48:packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容