大多数Android设备上的WiFi/BT用的都是单芯片,但却共用天线。这就需要WiFi、BT通过一定的机制合理分配天线的使用,因此,本文简单介绍一下Android上的WiFi、BT共存机制。
下图为共存机制的原理,是一个比较简单的机制:WiFi监听BT的工作状态,根据BT的工作状态来切换自己使用射频天线的时隙。

1. WiFi Service
frameworks/base/services/java/com/android/server/wifi/WifiService.java
public WifiService(Context context) {
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
boolean mWifiEnabled;
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_DISABLED);
mWifiEnabled = (wifiState == WifiManager.WIFI_STATE_ENABLED);
//bt wifi coexist by rda
if(mWifiEnabled){
int mode = 0;
if(mBluetoothState == BluetoothAdapter.STATE_CONNECTED ||
mBluetoothState == BluetoothAdapter.STATE_CONNECTING){
mode |= BT_STATE_CONNECTION_ON;
}
if(mScoState == BluetoothHeadset.STATE_AUDIO_CONNECTED){
mode |= BT_STATE_SCO_ON;
}
if(mA2dpState == BluetoothA2dp.STATE_PLAYING){
mode |= BT_STATE_A2DP_PLAYING;
}
mWifiStateMachine.setBtStateCommand(mode);
}
}
},
new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_ON)) {
mWifiController.sendMessage(CMD_SCREEN_ON);
}else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
int mode = BT_STATE_CONNECTION_OFF;
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
BluetoothAdapter.STATE_DISCONNECTED);
mBluetoothState = state;
if((state == BluetoothAdapter.STATE_DISCONNECTED) ||
(state == BluetoothAdapter.STATE_DISCONNECTING))
mode = BT_STATE_CONNECTION_OFF;
else
mode = BT_STATE_CONNECTION_ON;
mWifiStateMachine.setBtStateCommand(mode);
mWifiStateMachine.sendBluetoothAdapterStateChange(state);
} else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)){
int mode = -1;
mScoState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
if(mScoState == BluetoothHeadset.STATE_AUDIO_CONNECTED){
mode = BT_STATE_SCO_ON;
}else if(mScoState == BluetoothHeadset.STATE_AUDIO_CONNECTING){
mode = BT_STATE_SCO_ONGOING;
}else if((mScoState == BluetoothHeadset.STATE_AUDIO_DISCONNECTED)){
mode = BT_STATE_SCO_OFF;
}
mWifiStateMachine.setBtStateCommand(mode);
}
}
2.WifiStateMachine
Frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java
public class WifiStateMachine extends StateMachine {
public void setBtStateCommand(int mode){
sendMessage(CMD_BT_COEXIST,mode);
}
class DefaultState extends State {
@Override
public boolean processMessage(Message message) {
switch (message.what) {
case CMD_BT_COEXIST:
mWifiNative.setBluetoothCoexistenceMode(message.arg1);
break;
default:
loge("Error! unhandled message" + message);
break;
}
return HANDLED;
}
}
}
3.WifiNative
Frameworks/base/wifi/java/android/net/wifi/WifiNative.java
public class WifiNative {
public boolean setBluetoothCoexistenceMode(int mode) {
return doBooleanCommand("DRIVER BTCOEXMODE " + mode);
}
}
4.Wpa lib
wpa_supplicant_8_lib/driver_cmd_nl80211.c
int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
size_t buf_len )
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct ifreq ifr;
android_wifi_priv_cmd priv_cmd;
int ret = 0;
if (os_strcasecmp(cmd, "STOP") == 0) {
........
} else if( os_strncasecmp(cmd, "BTCOEXMODE", 10) == 0 ) {
int bt_state = -1;
ret = 0;
bt_state = atoi(cmd + 11);
memset(&ifr, 0, sizeof(ifr));
os_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
ifr.ifr_metric = bt_state;
if ((ret = ioctl(drv->global->ioctl_sock, BT_COEXIST, &ifr)) < 0) {
wpa_printf(MSG_ERROR, "%s: error ioctl[BT_COEXIST] ret= %d\n", __func__, ret);
return -1;
}
} else {
.........
}
return ret;
}
5.WiFi Driver
驱动收到BT_COEXIST命令会与芯片交互,每家WiFi芯片不同,做法不同。
















