Android平台上的WiFi BT共存机制
大多数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芯片不同,做法不同。