最近在解决wifi的一些问题,故研究下wifi源码。
该源码是基于Android4.3,其他版本略有改动,大致流程一样。
这篇主要说一下wifi的启动流程。
WifiManager
先从wifi的开启来看,WifiManager中提供了接口用来控制wifi开关,setWifiEnabled,参数true表示开启、false表示关闭。
public boolean setWifiEnabled(boolean enabled) {
try {
return mService.setWifiEnabled(enabled);
} catch (RemoteException e) {
return false;
}
}
该方法调用到WifiService中的setWifiEnabled。
WifiService
public synchronized boolean setWifiEnabled(boolean enable) {
enforceChangePermission();
Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
if (DBG) {
Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");
}
/*
* Caller might not have WRITE_SECURE_SETTINGS,
* only CHANGE_WIFI_STATE is enforced
*/
long ident = Binder.clearCallingIdentity();
try {
if (! mSettingsStore.handleWifiToggled(enable)) {
// Nothing to do if wifi cannot be toggled
return true;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
mWifiController.sendMessage(CMD_WIFI_TOGGLED);
return true;
}
enforceChangePermission 判断调用的进程是否有权限。想要开关wifi需要CHANGE_WIFI_STATE 权限。
handleWifiToggled 判断飞行模式、保存wifi 操作的状态。
向WifiController发送消息。CMD_WIFI_TOGGLED
WifiController
WifiController在WIfiService的构造函数中初始化、并开始运行。
WifiController继承了StateMachine,是一个状态机。其构造函数如下
WifiController(Context context, WifiService service, Looper looper) {
super(TAG, looper);
//....
addState(mDefaultState);
addState(mApStaDisabledState, mDefaultState);
addState(mStaEnabledState, mDefaultState);
addState(mDeviceActiveState, mStaEnabledState);
addState(mDeviceInactiveState, mStaEnabledState);
addState(mScanOnlyLockHeldState, mDeviceInactiveState);
addState(mFullLockHeldState, mDeviceInactiveState);
addState(mFullHighPerfLockHeldState, mDeviceInactiveState);
addState(mNoLockHeldState, mDeviceInactiveState);
addState(mStaDisabledWithScanState, mDefaultState);
addState(mApEnabledState, mDefaultState);
addState(mEcmState, mDefaultState);
if (mSettingsStore.isScanAlwaysAvailable()) {
setInitialState(mApStaDisabledState);
} else {
setInitialState(mApStaDisabledState);
}
}
上述函数中addState的格式,可以看出各状态之间的关系。
然后通过wifi是否可以一直扫描(isScanAlwaysAvailable)设置状态机初始状态。
ApStaDisabledState和StaDisabledWithScanState两种状态处理CMD_WIFI_TOGGLED消息时一样的。
看看ApStaDisabledState是如何处理的。
class ApStaDisabledState extends State {
private int mDeferredEnableSerialNumber = 0;