一:打开wifi。
进入wifi设置界面,相关文件WifiSettings.java
当用户点击android 设置按钮时,会创建wifisettings类,创建wifisettings类的条件应该在布局文件中指定,这个还不是太明白,有待研究。
由于wifisettings类是一个PreferenceFragment,当初始化wifisettings之后会调用onActivityCreated函数,
public void onActivityCreated(Bundle savedInstanceState) {
mWifiEnabler = new WifiEnabler(activity, actionBarSwitch); //创建wifienabler类
}
当用户点击wifi的开启按钮时候,会触发WifiEnabler里面的onCheckedChanged函数
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//Do nothing if called as a result of a state machine event
if (mStateMachineEvent) {
return;
}
// Show toast message if Wi-Fi is not allowed in airplane mode
if (isChecked && !WirelessSettings.isRadioAllowed(mContext, Settings.System.RADIO_WIFI)) {
Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
// Reset switch to off. No infinite check/listenenr loop.
buttonView.setChecked(false);
}
// Disable tethering if enabling Wifi
int wifiApState = mWifiManager.getWifiApState();
if (isChecked && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
(wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
mWifiManager.setWifiApEnabled(null, false);
}
if (mWifiManager.setWifiEnabled(isChecked)) {
// Intent has been taken into account, disable until new state is active
mSwitch.setEnabled(false);
} else {
// Error
Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show();
}
}
在onCheckedChanged函数里调用mWifiManager.setWifiEnabled函数,
在wifimanager.java中:
public boolean setWifiEnabled(boolean enabled) {
try {
return mService.setWifiEnabled(enabled);
} catch (RemoteException e) {
return false;
}
}
调用了mService.setWifiEnabled。
这里的mService是WifiService的代理,所以它实际调用的是wifiService里面的setWifiEnabled函数
mService的定义是 IWifiManager mService;
Iwifimanager的定义是public interface IWifiManager extends android.os.IInterface
而wifiservice的定义是public class WifiService extends IWifiManager.Stub,我们可以看到WifiService继承一个接口IWifiManager.Stub,凡是继承了像这种形式写法的接口服务,都可以进行远程调用,这就是Android内部的aidl通信。在wifiservice.java中:
public synchronized boolean setWifiEnabled(boolean enable) {
enforceChangePermission();
if (DBG) {
Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");
}
if (enable) {
reportStartWorkSource();
}
mWifiStateMachine.setWifiEnabled(enable);
/*
* Caller might not have WRITE_SECURE_SETTINGS,
* only CHANGE_WIFI_STATE is enforced
*/
/* Avoids overriding of airplane state when wifi is already in the expected state */
if (enable != mWifiEnabled) {
long ident = Binder.clearCallingIdentity();
persistWifiState(enable);
Binder.restoreCallingIdentity(ident);
}
if (enable) {
if (!mIsReceiverRegistered) {
registerForBroadcasts();
mIsReceiverRegistered = true;
}
} else if (mIsReceiverRegistered) {
mContext.unregisterReceiver(mReceiver);
mIsReceiverRegistered = false;
}
return true;
}
以上函数又调用了mWifiStateMachine.setWifiEnabled函数。
mWifiStateMachine是在Wifiservice的构造函数完成初始化的
WifiService(Context context) {
mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);
}
先介绍一下WifiStateMachine这个类,光看名字就知道wifi状态机,它里面记录了wifi的各种状态,driverUnloadedstate、mDriverUnloadingState、mDriverLoadingState、mDriverLoadedState、mSupplicantStartingState,每种状态都有enter()、exit()、processMessage()3个函数,分别处理进入该状态,退出该状态的动作,以及消息处理。在WifiStateMachine构造函数里面,它把所有状态都添加进状态机去,形成一个状态树,并在结尾出启动这个状态机工作。
public WifiStateMachine(Context context, String wlanInterface) {
addState(mDefaultState);
addState(mInitialState, mDefaultState);
addState(mDriverUnloadingState, mDefaultState);
addState(mDriverUnloadedState, mDefaultState);
addState(mDriverFailedState, mDriverUnloadedState);
addState(mDriverLoadingState, mDefaultState);
addState(mDriverLoadedState, mDefaultState);
addState(mSupplicantStartingState, mDefaultState);
addState(mSupplicantStartedState, mDefaultState);
addState(mDriverStartingState, mSupplicantStartedState);
addState(mDriverStartedState, mSupplicantStartedState);
addState(mScanModeState, mDriverStartedState);
addState(mConnectModeState, mDriverStartedState);
addState(mConnectingState, mConnectModeState);
addState(mConnectedState, mConnectModeState);
addState(mDisconnectingState, mConnectModeState);
addState(mDisconnectedState, mConnectModeState);
addState(mWaitForWpsCompletionState, mConnectModeState);
addState(mDriverStoppingState, mSupplicantStartedState);
addState(mDriverStoppedState, mSupplicantStartedState);
addState(mSupplicantStoppingState, mDefaultState);
addState(mSoftApStartingState, mDefaultState);
addState(mSoftApStartedState, mDefaultState);
addState(mTetheringState, mSoftApStartedState);
addState(mTetheredState, mSoftApStartedState);
addState(mSoftApStoppingState, mDefaultState);
addState(mWaitForP2pDisableState, mDefaultState);
。。。。。。。。。。
start();
}
再回到mWifiStateMachine.setWifiEnabled(enable)函数; public void setWifiEnabled(boolean enable) {
mLastEnableUid.set(Binder.getCallingUid());
if (enable) {
/* Argument is the state that is entered prior to load */
sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0));
sendMessage(CMD_START_SUPPLICANT);
} else {
sendMessage(CMD_STOP_SUPPLICANT);
/* Argument is the state that is entered upon success */
sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED, 0));
}
}
它做了两个动作,向状态机发送了2个消息
sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0));加载驱动
sendMessage(CMD_START_SUPPLICANT);开启supplicant
它在哪里处理的呢?
向状态机发送消息,当前状态会处理该消息。
而当前是什么状态呢?
状态机构造函数初始化时候,设置有个一个初始状态
setInitialState(mInitialState);
我们进入mInitialState状态看看
public void enter() {
if (WifiNative.isDriverLoaded()) {
transitionTo(mDriverLoadedState);
}
else {
transitionTo(mDriverUnloadedState);
}
因为最开始驱动都是没有加载的,所以进入transitionTo(mDriverUnloadedState);
transitionTo函数是状态切换的函数。
所以当前状态就是mDriverUnloadedState。
mDriverUnloadedState
class DriverUnloadedState extends State {
@Override
public boolean processMessage(Message message) {
switch (message.what) {
case CMD_LOAD_DRIVER:
mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING);
transitionTo(mWaitForP2pDisableState);
break;
case WifiP2pService.P2P_ENABLE_PENDING:
mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED);
break;
default:
return NOT_HANDLED;
}
EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
return HANDLED;
}
}
这里会处理刚才的CMD_LOAD_DRIVER这个消息,发送WIFI_ENABLE_PENDING到wifip2pservice,如果不支持p2p的话,
wifiservice会回复一个WIFI_ENABLE_PROCEED消息:
class P2pNotSupportedState extends State {
@Override
public boolean processMessage(Message message) {
switch (message.what) {
// Allow Wi-Fi to proceed
case WifiStateMachine.WIFI_ENABLE_PENDING:
replyToMessage(message, WIFI_ENABLE_PROCEED);
break;
然后继续切换到mWaitForP2pDisableState
class WaitForP2pDisableState extends State {
@Override
public boolean processMessage(Message message) {
if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case WifiP2pService.WIFI_ENABLE_PROCEED:
//restore argument from original message (CMD_LOAD_DRIVER)
message.arg1 = mSavedArg;
transitionTo(mDriverLoadingState);
break;
}
状态继续切换到mDriverLoadingState
class DriverLoadingState extends State {
@Override
public void enter() {
new Thread(new Runnable() {
public void run() {
mWakeLock.acquire();
//enabling state
switch(message.arg1) {
case WIFI_STATE_ENABLING:
setWifiState(WIFI_STATE_ENABLING);
break;
case WIFI_AP_STATE_ENABLING:
setWifiApState(WIFI_AP_STATE_ENABLING);
break;
}
if(WifiNative.loadDriver()) {
if (DBG) log("Driver load successful");
sendMessage(CMD_LOAD_DRIVER_SUCCESS);
} else {
loge("Failed to load driver!");
switch(message.arg1) {
case WIFI_STATE_ENABLING:
setWifiState(WIFI_STATE_UNKNOWN);
break;
case WIFI_AP_STATE_ENABLING:
setWifiApState(WIFI_AP_STATE_FAILED);
break;
}
sendMessage(CMD_LOAD_DRIVER_FAILURE);
}
mWakeLock.release();
}
}).start();
}
这里回调用WifiNative.loadDriver()加载驱动,成功后发送消息CMD_LOAD_DRIVER_SUCCESS,否则CMD_LOAD_DRIVER_FAILURE,进入JNI
static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
{
return (jboolean)(::wifi_load_driver() == 0);
}
会继续到wifi.c处理
int wifi_load_driver()
{
#ifdef WIFI_DRIVER_MODULE_PATH
char driver_status[PROPERTY_VALUE_MAX];
int count = 100; /* wait at most 20 seconds for completion */
int status = -1;
if (is_wifi_driver_loaded()) {
return 0;
}
/* ensure that wlan driver config file exists (if specified) */
if (ensure_wlan_driver_config_file_exists()) {
return -1;
}
property_set(DRIVER_PROP_NAME, "loading");
if(system(SDIO_POLLING_ON))
LOGW("Couldn't turn on SDIO polling: %s", SDIO_POLLING_ON);
if ('\0' != *DRIVER_SDIO_IF_MODULE_PATH) {
if (insmod(DRIVER_SDIO_IF_MODULE_PATH, DRIVER_SDIO_IF_MODULE_ARG) < 0) {
goto end;
}
}
if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) {
if ('\0' != *DRIVER_SDIO_IF_MODULE_NAME) {
rmmod(DRIVER_SDIO_IF_MODULE_NAME);
}
goto end;
}
if (strcmp(FIRMWARE_LOADER,"") == 0) {
/* usleep(WIFI_DRIVER_LOADER_DELAY); */
property_set(DRIVER_PROP_NAME, "ok");
}
else {
property_set("ctl.start", FIRMWARE_LOADER);
}
sched_yield();
while (count-- > 0) {
if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
if (strcmp(driver_status, "ok") == 0) {
status = 0;
goto end;
}
else if (strcmp(driver_status, "failed") == 0) {
_wifi_unload_driver();
goto end;
}
}
usleep(200000);
}
property_set(DRIVER_PROP_NAME, "timeout");
wifi_unload_driver();
end:
system(SDIO_POLLING_OFF);
return status;
#else
property_set(DRIVER_PROP_NAME, "ok");
return 0;
#endif
}
这里有几个比较重要的宏
#define WIFI_DRIVER_MODULE_PATH "/system/lib/modules/wlan.ko"驱动模块地址
static const char SUPP_CONFIG_FILE[] = "/data/misc/wifi/wpa_supplicant.conf"; supplicant配置文件
在这里wifi.c会跟wpa_supplicant通信,加载驱动成功后会发送消息CMD_LOAD_DRIVER_SUCCESS,
DriverLoadingState状态接收到CMD_LOAD_DRIVER_SUCCESS消息,然后处理:
public boolean processMessage(Message message) {
if (DBG) log(getName() + message.toString() + "\n");
switch (message.what) {
case CMD_LOAD_DRIVER_SUCCESS:
transitionTo(mDriverLoadedState);
break;
然后切换到DriverLoadedState状态。
来看另一个消息sendMessage(CMD_START_SUPPLICANT);,当前状态DriverLoadedState会处理该消息:
class DriverLoadedState extends State {
@Override
public boolean processMessage(Message message) {
case CMD_START_SUPPLICANT:
try {
mNwService.wifiFirmwareReload(mInterfaceName, "STA");
} catch (Exception e) {
loge("Failed to reload STA firmware " + e);
// continue
}
try {
mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
} catch (RemoteException re) {
loge("Unable to change interface settings: " + re);
} catch (IllegalStateException ie) {
loge("Unable to change interface settings: " + ie);
}
if(WifiNative.startSupplicant()) {
if (DBG) log("Supplicant start successful");
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
} else {
loge("Failed to start supplicant!");
sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
}
break;
继续调用JNI,WifiNative.startSupplicant(),过程差不多最后在wifi.c处理
int wifi_start_supplicant()
{
return wifi_start_supplicant_common(SUPP_CONFIG_FILE);
}
int wifi_start_supplicant_common(const char *config_file)
。。。。。。。
最后也是在这里跟Wpa_supplicant驱动通信.
当startSupplicant返回真时,会启动wifiMonitor线程来接收从wpa_supplicant发送的消息,之后切换到SupplicantStartingState状态。