您的位置:首页 > 产品设计 > UI/UE

android -- 蓝牙 bluetooth (二) 打开蓝牙

2014-08-28 09:25 281 查看
/article/2738612.html

4.2的蓝牙打开流程这一部分还是有些变化的,从界面上看蓝牙开关就是设置settings里那个switch开关,widget开关当然也可以,起点不同而已,后续的流程是一样的。先来看systemServer.java的代码,蓝牙服务开启的地方,最后一个else分支是我们关心的,前两个是模拟器的一个测试模式的。

[java] view
plaincopy

if (SystemProperties.get("ro.kernel.qemu").equals("1")) {

Slog.i(TAG, "No Bluetooh Service (emulator)");

} else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {

Slog.i(TAG, "No Bluetooth Service (factory test)");

} else {

Slog.i(TAG, "Bluetooth Manager Service");

bluetooth = new BluetoothManagerService(context);

ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);

}

暂且看下bluetoothManagerService的构造方法,代码有点多,我们只看两个地方, loadStoredNameAndAddress()是读取蓝牙打开默认名称的地方,isBluetoothPersistedStateOn()是判断是否已打开蓝牙的,如果已打开,后续操作要执行开启蓝牙的动作,前面那几行注册广播其中就有这个作用。

[java] view
plaincopy

BluetoothManagerService(Context context) {

...一些变量声明初始化...

IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);

filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);

filter.addAction(Intent.ACTION_USER_SWITCHED);

registerForAirplaneMode(filter);

mContext.registerReceiver(mReceiver, filter);

loadStoredNameAndAddress();

if (isBluetoothPersistedStateOn()) {

mEnableExternal = true;

}

}

回到界面开关那个看得着的地方,界面上开关就是BluetoothEnabler.java这个类了,而setBluetoothEnabled()则是具体开关动作。看下代码

[java] view
plaincopy

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

// Show toast message if Bluetooth is not allowed in airplane mode

if (isChecked &&

!WirelessSettings.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) {

Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();

// Reset switch to off

buttonView.setChecked(false);

}

if (mLocalAdapter != null) {

mLocalAdapter.setBluetoothEnabled(isChecked);

}

mSwitch.setEnabled(false);

}

这里在判断是飞行模式不知道为什么没有return,如果是飞行模式会有提示toast弹出,既然这样源码为什么还要执行下面打开流程呢,也许是个bug?不细究这个了,继续看setBluetoothEnabled()方法做什么了,很明显mLocalAdapter(LocalBluetoothAdapter )只是个过渡,里面的 mAdapter(BluetoothAdapter)才是真正的主角,代码如下:

[java] view
plaincopy

public void setBluetoothEnabled(boolean enabled) {

boolean success = enabled ? mAdapter.enable() : mAdapter.disable();

if (success) {

setBluetoothStateInt(enabled

? BluetoothAdapter.STATE_TURNING_ON

: BluetoothAdapter.STATE_TURNING_OFF);

} else {

.........

}

}

在BluetoothAdapter.java里可以看到一个单例模式的应用,主要提供给其它程序调用蓝牙的一些方法用的,外部程序想调用蓝牙的方法就要先用这个

拿到BluetoothAdapter对象,代码也简单看下吧,里面是典型的binder应用。

[java] view
plaincopy

public static synchronized BluetoothAdapter getDefaultAdapter() {

if (sAdapter == null) {

IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);

if (b != null) {

IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);

sAdapter = new BluetoothAdapter(managerService);

} else {

Log.e(TAG, "Bluetooth binder is null");

}

}

return sAdapter;

此时我们更关心mAdapter.enable()的后续操作,外部其它应用到getDefaultAdapter()也是调用enable(),注意,到了BluetoothAdapter我们已经在framework层了,顺着BluetoothAdapter.java的enable()调用先回到BluetoothManagerService.java的enable(),再进一步来到BluetoothManagerService.java中的handleEnable()

方法,后面要跳转到新类了,贴出来一起看下,这部分好像不同版本还有些出入,不过核心的启动service是一样的,不影响理解。

[java] view
plaincopy

private void handleEnable(boolean persist, boolean quietMode) {

synchronized(mConnection) {

if ((mBluetooth == null) && (!mBinding)) {

//Start bind timeout and bind

Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);

mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);

mConnection.setGetNameAddressOnly(false);

Intent i = new Intent(IBluetooth.class.getName());

if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE,

UserHandle.USER_CURRENT)) {

mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);

Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName());

} else {

mBinding = true;

}

}

下面跑到哪个service里去了呢,在log信息里可以看到"ActivityManager: Start proc com.android.bluetooth for service com.android.bluetooth/.btservice.AdapterService:"

这样的信息,那就是去AdapterService里看看,里面一共有三个enable(),跳转关系不复杂,我们直接看最后一个关键的。

[java] view
plaincopy

public synchronized boolean enable(boolean quietMode) {

enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,

"Need BLUETOOTH ADMIN permission");

if (DBG)debugLog("Enable called with quiet mode status = " + mQuietmode);

mQuietmode = quietMode;

Message m =

mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);

mAdapterStateMachine.sendMessage(m);

return true;

}

状态机来了,状态转换图,从一个状态接受命令跳到另一个状态,因为我们是在开启蓝牙,所以先去的AdapterState.java内部类offstate.java里面找,在这个分支USER_TURN_ON看到mAdapterService.processStart();在这里面可以看到蓝牙遍历下所支持的profile,最后又发出个带AdapterState.STARTED标识的消息

处理在同文件下面的代码里

[java] view
plaincopy

case STARTED: {

if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STARTED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);

//Remove start timeout

removeMessages(START_TIMEOUT);

//Enable

boolean ret = mAdapterService.enableNative();

if (!ret) {

Log.e(TAG, "Error while turning Bluetooth On");

notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);

transitionTo(mOffState);

} else {

sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);

}

看到那个enableNative()函数调用了吧,又要用到JNI了,稍微回头看下前面的代码,我们先从应用界面开关BluetoothEnabler走到framework的BluetoothAdapter,又回到package的adapterService,现在又要去JNI的C++代码了,往常一般是packages -->framework-->下面一层,这次顺序有些颠倒了,不过这不能影响我们跟踪代码,最后

还是要到下面去的。一起往下看吧。

根据android JNI的函数命名惯例很容易找到enableNative对应的C++函数在packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp里面

[java] view
plaincopy

static jboolean enableNative(JNIEnv* env, jobject obj) {

ALOGV("%s:",__FUNCTION__);

jboolean result = JNI_FALSE;

if (!sBluetoothInterface) return result;

int ret = sBluetoothInterface->enable();

result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

return result;

}

代码瞬间简洁了不少,看来更多的故事还在下面,sBluetoothInterface这是什么,直接关系到下一步去哪的问题,看下变量声明,原来是

Const bt_interface_t *sBluetoothInterface = NULL; 再去找在哪初始化,搜索external目录可以找到/external/bluetooth/bluedroid/btif/src/bluetooth.c

[cpp] view
plaincopy

static const bt_interface_t bluetoothInterface = {

sizeof(bt_interface_t),

init,

enable,

disable,

.............

start_discovery,

cancel_discovery,

create_bond,

remove_bond,

cancel_bond,

...............

};

原来在这里,说下怎么找到,直接跳转是不成了,看这个文件夹下的mk文件,那里面有libhardware目录是编译的时候要用到,这个多半在hardware目录里,在这里面很快可以看到bluetooth.h,那里面有最我们要找的结构体定义,头文件找到了,再找同名C文件就快了,好了继续吧看下enable()里是怎么实现的

[cpp] view
plaincopy

static int enable( void )

{

ALOGI("enable");

/* sanity check */

if (interface_ready() == FALSE)

return BT_STATUS_NOT_READY;

return btif_enable_bluetooth();

}

又是一个新函数,直接跳转,比起刚才的寻觅这太幸福了

[cpp] view
plaincopy

bt_status_t btif_enable_bluetooth(void)

{

BTIF_TRACE_DEBUG0("BTIF ENABLE BLUETOOTH");

if (btif_core_state != BTIF_CORE_STATE_DISABLED)

{

ALOGD("not disabled\n");

return BT_STATUS_DONE;

}

btif_core_state = BTIF_CORE_STATE_ENABLING;

/* Create the GKI tasks and run them */

bte_main_enable(btif_local_bd_addr.address);

return BT_STATUS_SUCCESS;

}

忘了写路径了 好在可以直接跳转,下面是/external/bluetooth/bluedroid/main/bte_main.c,有点长,暂时只关心set_power那部分就好了,

[cpp] view
plaincopy

void bte_main_enable(uint8_t *local_addr)

{

APPL_TRACE_DEBUG1("%s", __FUNCTION__);

........................

#if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)

APPL_TRACE_DEBUG1("%s Not Turninig Off the BT before Turninig ON", __FUNCTION__);

#else

/* toggle chip power to ensure we will reset chip in case

a previous stack shutdown wasn't completed gracefully */

bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF);

#endif

bt_hc_if->set_power(BT_HC_CHIP_PWR_ON);

bt_hc_if->preload(NULL);

}

.............................

}

路径在这里/external/bluetooth/bluedroid/hci/src/bt_hci_bdroid.c,看看set_power里面有什么,快到头了

[cpp] view
plaincopy

static void set_power(bt_hc_chip_power_state_t state)

{

int pwr_state;

BTHCDBG("set_power %d", state);

/* Calling vendor-specific part */

pwr_state = (state == BT_HC_CHIP_PWR_ON) ? BT_VND_PWR_ON : BT_VND_PWR_OFF;

if (bt_vnd_if)

bt_vnd_if->op(BT_VND_OP_POWER_CTRL, &pwr_state);

else

ALOGE("vendor lib is missing!");

}

这下又有新东西了bt_vnd_if,这个是什么,bt_vendor_interface_t *bt_vnd_if=NULL;和刚才的bt_interface_t 一样,我们希望可以找到它的初始化,那样就可以继续跟踪了,不过看到下面的代码和注释,在源码中我们要绝望了。路径:/external/bluetooth/bluedroid/hci/include/bt_vendor_lib.h

[cpp] view
plaincopy

/* Entry point of DLib --

* Vendor library needs to implement the body of bt_vendor_interface_t

* structure and uses the below name as the variable name. HCI library

* will use this symbol name to get address of the object through the

* dlsym call.

*/

extern const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE;

bt_vendor_interface_t *bt_vnd_if=NULL;

google定义好了接口,具体实现要看vendor厂商来做了,这后面怎么实现就看各家芯片商怎么写了,肯定各有不同,而且这一部分代码一般是不会公开,当然授权购买后除外了。所以在4.2的源码中我们只跟到这里了,那后面会做什么呢,加载驱动和上电这两项肯定要有了,打开蓝牙没这两步怎么行,类似下面的字符串

[cpp] view
plaincopy

static const char* BT_DRIVER_MODULE_PATH = "/system/lib/modules/mbt8xxx.ko";

static const char* BT_DRIVER_MODULE_NAME = "bt8xxx";

static const char* BT_DRIVER_MODULE_INIT_ARG = " init_cfg=";

static const char* BT_DRIVER_MODULE_INIT_CFG_PATH = "bt_init_cfg.conf";

在有类似下面的动作,insmod加载驱动,rfkill控制上下电,具体厂商具体做法也不同。

[cpp] view
plaincopy

ret = insmod(BT_DRIVER_MODULE_PATH, arg_buf);

ret = system("/system/bin/rfkill block all");

写到这,关于4.2源码的蓝牙打开流程就算结束了,比起4.1之前的代码感觉没有以前的直观,对于vendor那部分的代码大家只能看各自厂商的代码了,一般蓝牙开启后才会上电,这样也比较符合逻辑和节省电量,是否上电可以连上手机用adb shell看sys/class/rfkill目录下的state状态值,有些厂商会把蓝牙和wifi的上电算在一起,这个也是要注意的,小心误判。最后呢,这次文章写得有点仓促,写错的或遗漏地方希望朋友指出来,非常感谢。

[java] view
plaincopy

BluetoothManagerService(Context context) {

...一些变量声明初始化...

IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);

filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);

filter.addAction(Intent.ACTION_USER_SWITCHED);

registerForAirplaneMode(filter);

mContext.registerReceiver(mReceiver, filter);

loadStoredNameAndAddress();

if (isBluetoothPersistedStateOn()) {

mEnableExternal = true;

}

}

回到界面开关那个看得着的地方,界面上开关就是BluetoothEnabler.java这个类了,而setBluetoothEnabled()则是具体开关动作。看下代码

[java] view
plaincopy

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

// Show toast message if Bluetooth is not allowed in airplane mode

if (isChecked &&

!WirelessSettings.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) {

Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();

// Reset switch to off

buttonView.setChecked(false);

}

if (mLocalAdapter != null) {

mLocalAdapter.setBluetoothEnabled(isChecked);

}

mSwitch.setEnabled(false);

}

这里在判断是飞行模式不知道为什么没有return,如果是飞行模式会有提示toast弹出,既然这样源码为什么还要执行下面打开流程呢,也许是个bug?不细究这个了,继续看setBluetoothEnabled()方法做什么了,很明显mLocalAdapter(LocalBluetoothAdapter )只是个过渡,里面的 mAdapter(BluetoothAdapter)才是真正的主角,代码如下:

[java] view
plaincopy

public void setBluetoothEnabled(boolean enabled) {

boolean success = enabled ? mAdapter.enable() : mAdapter.disable();

if (success) {

setBluetoothStateInt(enabled

? BluetoothAdapter.STATE_TURNING_ON

: BluetoothAdapter.STATE_TURNING_OFF);

} else {

.........

}

}

在BluetoothAdapter.java里可以看到一个单例模式的应用,主要提供给其它程序调用蓝牙的一些方法用的,外部程序想调用蓝牙的方法就要先用这个

拿到BluetoothAdapter对象,代码也简单看下吧,里面是典型的binder应用。

[java] view
plaincopy

public static synchronized BluetoothAdapter getDefaultAdapter() {

if (sAdapter == null) {

IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);

if (b != null) {

IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);

sAdapter = new BluetoothAdapter(managerService);

} else {

Log.e(TAG, "Bluetooth binder is null");

}

}

return sAdapter;

此时我们更关心mAdapter.enable()的后续操作,外部其它应用到getDefaultAdapter()也是调用enable(),注意,到了BluetoothAdapter我们已经在framework层了,顺着BluetoothAdapter.java的enable()调用先回到BluetoothManagerService.java的enable(),再进一步来到BluetoothManagerService.java中的handleEnable()

方法,后面要跳转到新类了,贴出来一起看下,这部分好像不同版本还有些出入,不过核心的启动service是一样的,不影响理解。

[java] view
plaincopy

private void handleEnable(boolean persist, boolean quietMode) {

synchronized(mConnection) {

if ((mBluetooth == null) && (!mBinding)) {

//Start bind timeout and bind

Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);

mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);

mConnection.setGetNameAddressOnly(false);

Intent i = new Intent(IBluetooth.class.getName());

if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE,

UserHandle.USER_CURRENT)) {

mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);

Log.e(TAG, "Fail to bind to: " + IBluetooth.class.getName());

} else {

mBinding = true;

}

}

下面跑到哪个service里去了呢,在log信息里可以看到"ActivityManager: Start proc com.android.bluetooth for service com.android.bluetooth/.btservice.AdapterService:"

这样的信息,那就是去AdapterService里看看,里面一共有三个enable(),跳转关系不复杂,我们直接看最后一个关键的。

[java] view
plaincopy

public synchronized boolean enable(boolean quietMode) {

enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,

"Need BLUETOOTH ADMIN permission");

if (DBG)debugLog("Enable called with quiet mode status = " + mQuietmode);

mQuietmode = quietMode;

Message m =

mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);

mAdapterStateMachine.sendMessage(m);

return true;

}

状态机来了,状态转换图,从一个状态接受命令跳到另一个状态,因为我们是在开启蓝牙,所以先去的AdapterState.java内部类offstate.java里面找,在这个分支USER_TURN_ON看到mAdapterService.processStart();在这里面可以看到蓝牙遍历下所支持的profile,最后又发出个带AdapterState.STARTED标识的消息

处理在同文件下面的代码里

[java] view
plaincopy

case STARTED: {

if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STARTED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);

//Remove start timeout

removeMessages(START_TIMEOUT);

//Enable

boolean ret = mAdapterService.enableNative();

if (!ret) {

Log.e(TAG, "Error while turning Bluetooth On");

notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);

transitionTo(mOffState);

} else {

sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);

}

看到那个enableNative()函数调用了吧,又要用到JNI了,稍微回头看下前面的代码,我们先从应用界面开关BluetoothEnabler走到framework的BluetoothAdapter,又回到package的adapterService,现在又要去JNI的C++代码了,往常一般是packages -->framework-->下面一层,这次顺序有些颠倒了,不过这不能影响我们跟踪代码,最后

还是要到下面去的。一起往下看吧。

根据android JNI的函数命名惯例很容易找到enableNative对应的C++函数在packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp里面

[java] view
plaincopy

static jboolean enableNative(JNIEnv* env, jobject obj) {

ALOGV("%s:",__FUNCTION__);

jboolean result = JNI_FALSE;

if (!sBluetoothInterface) return result;

int ret = sBluetoothInterface->enable();

result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

return result;

}

代码瞬间简洁了不少,看来更多的故事还在下面,sBluetoothInterface这是什么,直接关系到下一步去哪的问题,看下变量声明,原来是

Const bt_interface_t *sBluetoothInterface = NULL; 再去找在哪初始化,搜索external目录可以找到/external/bluetooth/bluedroid/btif/src/bluetooth.c

[cpp] view
plaincopy

static const bt_interface_t bluetoothInterface = {

sizeof(bt_interface_t),

init,

enable,

disable,

.............

start_discovery,

cancel_discovery,

create_bond,

remove_bond,

cancel_bond,

...............

};

原来在这里,说下怎么找到,直接跳转是不成了,看这个文件夹下的mk文件,那里面有libhardware目录是编译的时候要用到,这个多半在hardware目录里,在这里面很快可以看到bluetooth.h,那里面有最我们要找的结构体定义,头文件找到了,再找同名C文件就快了,好了继续吧看下enable()里是怎么实现的

[cpp] view
plaincopy

static int enable( void )

{

ALOGI("enable");

/* sanity check */

if (interface_ready() == FALSE)

return BT_STATUS_NOT_READY;

return btif_enable_bluetooth();

}

又是一个新函数,直接跳转,比起刚才的寻觅这太幸福了

[cpp] view
plaincopy

bt_status_t btif_enable_bluetooth(void)

{

BTIF_TRACE_DEBUG0("BTIF ENABLE BLUETOOTH");

if (btif_core_state != BTIF_CORE_STATE_DISABLED)

{

ALOGD("not disabled\n");

return BT_STATUS_DONE;

}

btif_core_state = BTIF_CORE_STATE_ENABLING;

/* Create the GKI tasks and run them */

bte_main_enable(btif_local_bd_addr.address);

return BT_STATUS_SUCCESS;

}

忘了写路径了 好在可以直接跳转,下面是/external/bluetooth/bluedroid/main/bte_main.c,有点长,暂时只关心set_power那部分就好了,

[cpp] view
plaincopy

void bte_main_enable(uint8_t *local_addr)

{

APPL_TRACE_DEBUG1("%s", __FUNCTION__);

........................

#if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)

APPL_TRACE_DEBUG1("%s Not Turninig Off the BT before Turninig ON", __FUNCTION__);

#else

/* toggle chip power to ensure we will reset chip in case

a previous stack shutdown wasn't completed gracefully */

bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF);

#endif

bt_hc_if->set_power(BT_HC_CHIP_PWR_ON);

bt_hc_if->preload(NULL);

}

.............................

}

路径在这里/external/bluetooth/bluedroid/hci/src/bt_hci_bdroid.c,看看set_power里面有什么,快到头了

[cpp] view
plaincopy

static void set_power(bt_hc_chip_power_state_t state)

{

int pwr_state;

BTHCDBG("set_power %d", state);

/* Calling vendor-specific part */

pwr_state = (state == BT_HC_CHIP_PWR_ON) ? BT_VND_PWR_ON : BT_VND_PWR_OFF;

if (bt_vnd_if)

bt_vnd_if->op(BT_VND_OP_POWER_CTRL, &pwr_state);

else

ALOGE("vendor lib is missing!");

}

这下又有新东西了bt_vnd_if,这个是什么,bt_vendor_interface_t *bt_vnd_if=NULL;和刚才的bt_interface_t 一样,我们希望可以找到它的初始化,那样就可以继续跟踪了,不过看到下面的代码和注释,在源码中我们要绝望了。路径:/external/bluetooth/bluedroid/hci/include/bt_vendor_lib.h

[cpp] view
plaincopy

/* Entry point of DLib --

* Vendor library needs to implement the body of bt_vendor_interface_t

* structure and uses the below name as the variable name. HCI library

* will use this symbol name to get address of the object through the

* dlsym call.

*/

extern const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE;

bt_vendor_interface_t *bt_vnd_if=NULL;

google定义好了接口,具体实现要看vendor厂商来做了,这后面怎么实现就看各家芯片商怎么写了,肯定各有不同,而且这一部分代码一般是不会公开,当然授权购买后除外了。所以在4.2的源码中我们只跟到这里了,那后面会做什么呢,加载驱动和上电这两项肯定要有了,打开蓝牙没这两步怎么行,类似下面的字符串

[cpp] view
plaincopy

static const char* BT_DRIVER_MODULE_PATH = "/system/lib/modules/mbt8xxx.ko";

static const char* BT_DRIVER_MODULE_NAME = "bt8xxx";

static const char* BT_DRIVER_MODULE_INIT_ARG = " init_cfg=";

static const char* BT_DRIVER_MODULE_INIT_CFG_PATH = "bt_init_cfg.conf";

在有类似下面的动作,insmod加载驱动,rfkill控制上下电,具体厂商具体做法也不同。

[cpp] view
plaincopy

ret = insmod(BT_DRIVER_MODULE_PATH, arg_buf);

ret = system("/system/bin/rfkill block all");

写到这,关于4.2源码的蓝牙打开流程就算结束了,比起4.1之前的代码感觉没有以前的直观,对于vendor那部分的代码大家只能看各自厂商的代码了,一般蓝牙开启后才会上电,这样也比较符合逻辑和节省电量,是否上电可以连上手机用adb shell看sys/class/rfkill目录下的state状态值,有些厂商会把蓝牙和wifi的上电算在一起,这个也是要注意的,小心误判。最后呢,这次文章写得有点仓促,写错的或遗漏地方希望朋友指出来,非常感谢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: