标签:
上一章我们讲到在SystemServer中会初始化一个WifiService对象,那么我们来看看这个WifiService的构造方法,路径:./frameworks/base/services/java/com/android/server/wifi/WifiService.java
<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> public WifiService(Context context) {
mContext = context;
mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");
mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);
mWifiStateMachine.enableRssiPolling(true);
mBatteryStats = BatteryStatsService.getService();
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);
mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);
mSettingsStore = new WifiSettingsStore(mContext);
HandlerThread wifiThread = new HandlerThread("WifiService");
wifiThread.start();
mClientHandler = new ClientHandler(wifiThread.getLooper());
mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
mWifiController = new WifiController(mContext, this, wifiThread.getLooper());
mWifiController.start();
mBatchedScanSupported = mContext.getResources().getBoolean(
R.bool.config_wifi_batched_scan_supported);
registerForScanModeChange();
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
///M: modify for timing issue to access Settings.Global.AIRPLANE_MODE_ON
boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
SXlog.i(TAG, "ACTION_AIRPLANE_MODE_CHANGED isAirplaneModeOn="+isAirplaneModeOn);
if (mSettingsStore.handleAirplaneModeToggled(isAirplaneModeOn)) {
mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
}
}
},
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
// Adding optimizations of only receiving broadcasts when wifi is enabled
// can result in race conditions when apps toggle wifi in the background
// without active user involvement. Always receive broadcasts.
registerForBroadcasts();
///M:
initializeExtra();
}</span></span></span>WifiStateMachine用于控制整个Wifi的开启、关闭、连接、断开的状态切换,它继承了StateMachine,来看看构造方法的关键代码,路径为:./frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java
<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;">public WifiStateMachine(Context context, String wlanInterface) {
super("WifiStateMachine");
addState(mDefaultState);
addState(mInitialState, mDefaultState);
addState(mSupplicantStartingState, mDefaultState);
addState(mSupplicantStartedState, mDefaultState);
addState(mDriverStartingState, mSupplicantStartedState);
addState(mDriverStartedState, mSupplicantStartedState);
addState(mScanModeState, mDriverStartedState);
addState(mConnectModeState, mDriverStartedState);
addState(mL2ConnectedState, mConnectModeState);
addState(mObtainingIpState, mL2ConnectedState);
addState(mVerifyingLinkState, mL2ConnectedState);
addState(mCaptivePortalCheckState, mL2ConnectedState);
addState(mConnectedState, mL2ConnectedState);
addState(mDisconnectingState, mConnectModeState);
addState(mDisconnectedState, mConnectModeState);
addState(mWpsRunningState, mConnectModeState);
addState(mWaitForP2pDisableState, mSupplicantStartedState);
addState(mDriverStoppingState, mSupplicantStartedState);
addState(mDriverStoppedState, mSupplicantStartedState);
addState(mSupplicantStoppingState, mDefaultState);
addState(mSoftApStartingState, mDefaultState);
addState(mSoftApStartedState, mDefaultState);
addState(mTetheringState, mSoftApStartedState);
addState(mTetheredState, mSoftApStartedState);
addState(mUntetheringState, mSoftApStartedState);
setInitialState(mInitialState);
//start the state machine
start();
}</span></span></span>
回到WifiService的构造方法中,还有一个WifiController对象被创建,WifiController类也是StateMachine的子类,看看其构造方法,路径:./frameworks/base/services/java/com/android/server/wifi/WifiController.java
<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;">WifiController(Context context, WifiService service, Looper looper) {
super(TAG, looper);
mContext = context;
mWifiStateMachine = service.mWifiStateMachine;
mSettingsStore = service.mSettingsStore;
mLocks = service.mLocks;
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
mIdleIntent = PendingIntent.getBroadcast(mContext, IDLE_REQUEST, idleIntent, 0);
///M: add plugin
mWifiFwkExt = MediatekClassFactory.createInstance(IWifiFwkExt.class, mContext);
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(mStaDisabledWithScanState);
} else {
setInitialState(mApStaDisabledState);
}
setLogRecSize(100);
setLogOnlyTransitions(false);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_DEVICE_IDLE);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(ACTION_DEVICE_IDLE)) {
sendMessage(CMD_DEVICE_IDLE);
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO);
}
}
},
new IntentFilter(filter));
initializeAndRegisterForSettingsChange(looper);
}</span></span></span>在WifiService构造方法中创建了WifiController对象了就立即调用了它的start方法,所以此时WifiController所在状态为它的初始状态,那么它的初始状态为什么呢?我们可以看到当系统在Wifi关闭的状态下仍然可以扫描时,那么初始状态为mStaDisabledWithScanState,否则为mApStaDisabledState,目前我们的系统的初始状态应该属于后者,也就是mApStaDisabledState,那我们进入到其enter方法中
<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;">@Override
public void enter() {
if (DBG) log(getName() + "\n");
mWifiStateMachine.setSupplicantRunning(false);
// Supplicant can't restart right away, so not the time we switched off
mDisabledTimestamp = SystemClock.elapsedRealtime();
mDeferredEnableSerialNumber++;
mHaveDeferredEnable = false;
}</span></span></span>在之前的SystemServer中,在WifiService对象创建之后,我们还调用了它的checkAndStartWifi方法,这个方法就是用来检测是否可以启动Wifi了
<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> /**
* Check if Wi-Fi needs to be enabled and start
* if needed
*
* This function is used only at boot time
*/
public void checkAndStartWifi() {
///M:
mWifiStateMachine.autoConnectInit();
/* Check if wi-fi needs to be enabled */
boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
///M: @{
if (mWifiStateMachine.hasCustomizedAutoConnect() && mSettingsStore.isAirplaneModeOn()) {
SXlog.i(TAG, "Don't enable wifi when airplane mode is on for customization.");
} else {
///@}
Slog.i(TAG, "WifiService starting up with Wi-Fi " +
(wifiEnabled ? "enabled" : "disabled"));
// If we are already disabled (could be due to airplane mode), avoid changing persist
// state here
if (wifiEnabled) setWifiEnabled(wifiEnabled);
}
mWifiWatchdogStateMachine = WifiWatchdogStateMachine.
makeWifiWatchdogStateMachine(mContext);
}</span></span></span><span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> /**
* see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
* @param enable {@code true} to enable, {@code false} to disable.
* @return {@code true} if the enable/disable operation was
* started or is already in the queue.
*/
public synchronized boolean setWifiEnabled(boolean enable) {
Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
enforceChangePermission();
///M: @{
if (mWifiStateMachine.hasCustomizedAutoConnect() && enable && mSettingsStore.isAirplaneModeOn()) {
SXlog.i(TAG, "Can't enable wifi when airplane mode is on for customization.");
return false;
}
///@}
if (DBG) {
Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");
}
if (FeatureOption.MTK_MOBILE_MANAGEMENT) {
if (enable == true) {
if (mMobileManagerService == null) {
mMobileManagerService = IMobileManagerService.Stub.asInterface(
ServiceManager.getService(Context.MOBILE_SERVICE));
}
try {
mMobileManagerService.checkPermissionAsync(SubPermissions.CHANGE_WIFI_STATE_ON,
Binder.getCallingUid(), new wifiOnPermissionCheckCallback());
} catch (RemoteException e) {
Slog.e(TAG, "checkPermissionAsync() failed", e);
}
return true;
}
}
/*
* 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);
}
///M: put extra mWifiIpoOff
Log.e("dd","mWifiIpoOff1="+String.valueOf(mWifiIpoOff));
mWifiController.obtainMessage(CMD_WIFI_TOGGLED, mWifiIpoOff ? 1 : 0 ).sendToTarget();
return true;
}</span></span></span><span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> @Override
public boolean processMessage(Message msg) {
SXlog.d(TAG, getName() + msg.toString() + "\n");
switch (msg.what) {
case CMD_WIFI_TOGGLED:
case CMD_AIRPLANE_TOGGLED:
///M: add WifiIpoOff@{
boolean wifiIpoOff = (msg.arg1==1) ? true: false;
boolean ipoStateChange= false;
if(mWifiIpoOff!=wifiIpoOff) ipoStateChange=true;
mWifiIpoOff = wifiIpoOff;
if(wifiIpoOff ==true){
SXlog.d(TAG,"ipooff don't enable wifi\n");
break;
}
if (mSettingsStore.isWifiToggleEnabled()) {
//@}
if (doDeferEnable(msg)) {
if (mHaveDeferredEnable) {
// have 2 toggles now, inc serial number an ignore both
mDeferredEnableSerialNumber++;
}
mHaveDeferredEnable = !mHaveDeferredEnable;
break;
}
if (mDeviceIdle == false) {
Log.e("dd","ApStaDisabledState to mDeviceActiveState");
transitionTo(mDeviceActiveState);
} else {
checkLocksAndTransitionWhenDeviceIdle();
}
///M: check scan always avaliable only when ipo change from ipo on to off
}else if (ipoStateChange ==true && mSettingsStore.isScanAlwaysAvailable() && mSettingsStore.isAirplaneModeOn()==false ) {
SXlog.d(TAG,"ipoStateChange = "+ipoStateChange + "isAirplaneModeOn= "+mSettingsStore.isAirplaneModeOn());
transitionTo(mStaDisabledWithScanState);
}
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}</span></span></span><span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> class StaEnabledState extends State {
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(true);
}
class DeviceActiveState extends State {
@Override
public void enter() {
mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
mWifiStateMachine.setDriverStart(true);
mWifiStateMachine.setHighPerfModeEnabled(false);
}</span></span></span>先来看看处理CMD_START_SUPPLICANT消息的地方
<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;">@Override
public boolean processMessage(Message message) {
if (DBG) log(getName() + message.toString() + "\n");
switch (message.what) {
case CMD_START_SUPPLICANT:
setWifiState(WIFI_STATE_ENABLING);
if (mWifiNative.loadDriver()) {
try {
mNwService.wifiFirmwareReload(mInterfaceName, "STA");
} catch (Exception e) {
loge("Failed to reload STA firmware " + e);
// continue
}
try {
// A runtime crash can leave the interface up and
// this affects connectivity when supplicant starts up.
// Ensure interface is down before a supplicant start.
mNwService.setInterfaceDown(mInterfaceName);
// Set privacy extensions
mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
// IPv6 is enabled only as long as access point is connected since:
// - IPv6 addresses and routes stick around after disconnection
// - kernel is unaware when connected and fails to start IPv6 negotiation
// - kernel can start autoconfiguration when 802.1x is not complete
mNwService.disableIpv6(mInterfaceName);
} catch (RemoteException re) {
loge("Unable to change interface settings: " + re);
} catch (IllegalStateException ie) {
loge("Unable to change interface settings: " + ie);
}
/* Stop a running supplicant after a runtime restart
* Avoids issues with drivers that do not handle interface down
* on a running supplicant properly.
*/
mWifiMonitor.killSupplicant(mP2pSupported);
if(mWifiNative.startSupplicant(mP2pSupported)) {
if (DBG) log("Supplicant start successful");
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
} else {
loge("Failed to start supplicant!");
}
} else {
loge("Failed to load driver");
}
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
}</span></span></span><span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> public synchronized void startMonitoring(String iface) {
WifiMonitor m = mIfaceMap.get(iface);
if (m == null) {
Log.e(TAG, "startMonitor called with unknown iface=" + iface);
return;
}
Log.d(TAG, "startMonitoring(" + iface + ") with mConnected = " + mConnected);
if (mConnected) {
m.mMonitoring = true;
m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT);
} else {
if (DBG) Log.d(TAG, "connecting to supplicant");
int connectTries = 0;
while (true) {
if (mWifiNative.connectToSupplicant()) {
m.mMonitoring = true;
m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT);
new MonitorThread(mWifiNative, this).start();
mConnected = true;
break;
}
if (connectTries++ < 5) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignore) {
}
} else {
Log.d(TAG, "rmIfaceMap remove " + iface);
mIfaceMap.remove(iface);
///M:@{
if (!m.mInterfaceName.equals("ap0")) {
m.mWifiStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
}
///@}
Log.e(TAG, "startMonitoring(" + iface + ") failed! " );
break;
}
}
}
</span></span></span>这个方法里面主要调用WifiNative的connenctToSupplicant去和wpa_supplicant建立socket连接,然后给WifiStateMachine发送一个SUP_CONNECTION_EVENT消息,最后新建一个MonitorThread运行,MonitorThread就是一个循环,不断的从wpa_supplicant收event,然后进行解析,并dispatch到不同的函数去处理,后面我们再来分析MonitorThread的流程。回到WifiStateMachine的InitialState中去看看如何处理CMD_START_SUPPLICANT的流程中来,当startMonitoring结束后,WifiStateMachine就跳转到SupplicantStartingState。
接着来看当WifiStateMachine处理完SUP_CONNECTION_EVENT消息后,马上会收到SET_OPERATIONAL_MODE和CMD_START_DRIVER消息,这两个消息都会被SupplicantStartingState延迟处理,SET_HTGH_PERF_MODE会被DefaultState处理。接着SupplicantStartingState会收到SUP_CONNECTION_EVENT,处理代码如下:
<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> @Override
public boolean processMessage(Message message) {
if (DBG) log(getName() + message.toString() + "\n");
switch(message.what) {
case WifiMonitor.SUP_CONNECTION_EVENT:
if (DBG) log("Supplicant connection established");
setWifiState(WIFI_STATE_ENABLED);
mSupplicantRestartCount = 0;
/* Reset the supplicant state to indicate the supplicant
* state is not known at this time */
mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
/* Initialize data structures */
mLastBssid = null;
mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
mLastSignalLevel = -1;
mWifiInfo.setMacAddress(mWifiNative.getMacAddress());
mWifiConfigStore.loadAndEnableAllNetworks();
initializeWpsDetails();
mStopSupplicantScan = false;
mConnectNetwork = false;
mLastExplicitNetworkId = INVALID_NETWORK_ID;
mOnlineStartTime = 0;
mUsingPppoe = false;
if (mWifiFwkExt.hasCustomizedAutoConnect()) {
mWifiNative.setBssExpireAge(IWifiFwkExt.BSS_EXPIRE_AGE);
mWifiNative.setBssExpireCount(IWifiFwkExt.BSS_EXPIRE_COUNT);
mDisconnectOperation = false;
mScanForWeakSignal = false;
mShowReselectDialog = false;
if (!mWifiFwkExt.shouldAutoConnect()) {
disableAllNetworks(false);
}
}
if (FeatureOption.MTK_EAP_SIM_AKA) {
if (isAirplaneModeOn()) {
List<WifiConfiguration> networks = mWifiConfigStore.getConfiguredNetworks();
if (null != networks) {
for (WifiConfiguration network : networks) {
int value = network.enterpriseConfig.getEapMethod();
Xlog.d(TAG, "EAP value:" + value);
if (value == WifiEnterpriseConfig.Eap.SIM || value == WifiEnterpriseConfig.Eap.AKA) {
mWifiConfigStore.disableNetwork(network.networkId,
WifiConfiguration.DISABLED_UNKNOWN_REASON);
}
}
} else {
Xlog.d(TAG, "Check for EAP_SIM_AKA, networks is null!");
}
}
}
sendSupplicantConnectionChangedBroadcast(true);
transitionTo(mDriverStartedState);
break;
case WifiMonitor.SUP_DISCONNECTION_EVENT:
if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) {
loge("Failed to setup control channel, restart supplicant");
mWifiMonitor.killSupplicant(mP2pSupported);
transitionTo(mInitialState);
sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
} else {
loge("Failed " + mSupplicantRestartCount +
" times to start supplicant, unload driver");
mSupplicantRestartCount = 0;
setWifiState(WIFI_STATE_UNKNOWN);
transitionTo(mInitialState);
}
break;
case CMD_START_SUPPLICANT:
case CMD_STOP_SUPPLICANT:
case CMD_START_AP:
case CMD_STOP_AP:
case CMD_START_DRIVER:
case CMD_STOP_DRIVER:
case CMD_SET_OPERATIONAL_MODE:
case CMD_SET_COUNTRY_CODE:
case CMD_SET_FREQUENCY_BAND:
case CMD_START_PACKET_FILTERING:
case CMD_STOP_PACKET_FILTERING:
deferMessage(message);
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}</span></span></span>在SUP_CONNECTION_EVENT的处理流程中,主要是调用WifiConfigStore的loadAndEnableAllNetworks函数来加载并enable用户之前连接过并保存的AP,然后会初始化一些Wps相关的信息,最后transition到DriverStartedState上。再来看DriverStartedState的enter函数,这里面有一些重要的流程:
<span style="font-size:14px;"><span style="font-size:12px;"><span style="font-size:10px;"> class DriverStartedState extends State {
@Override
public void enter() {
/* set country code */
setCountryCode();
/* set frequency band of operation */
setFrequencyBand();
/* initialize network state */
setNetworkDetailedState(DetailedState.DISCONNECTED);
mDhcpActive = false;
startBatchedScan();
if (mOperationalMode != CONNECT_MODE) {
mWifiNative.disconnect();
mWifiConfigStore.disableAllNetworks();
if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) {
setWifiState(WIFI_STATE_DISABLED);
}
transitionTo(mScanModeState);
} else {
/* Driver stop may have disabled networks, enable right after start */
mWifiConfigStore.enableAllNetworks();
if (DBG) log("Attempting to reconnect to wifi network ..");
mWifiNative.reconnect();
// Status pulls in the current supplicant state and network connection state
// events over the monitor connection. This helps framework sync up with
// current supplicant state
mWifiNative.status();
transitionTo(mDisconnectedState);
}</span></span></span>enter函数的代码比较多,上面是精简后的代码,上面主要分为两条分支,一是OperationalMode != CONNECT_MODE,一种是OperationalMode = CONNECT_MODE,根据官方的解释,OperationalMode一共有三种,分别如下:
1.CONNECT_MODE,这种模式下,STA可以scan并连接热点
2.SCAN_ONLY_MODE,这种模式下,STA只能扫描热点
3.SCAN_ONLY_WIFI_OFF_MODE,在这种模式下,当wifi是toggle off的情况下,也可以进行scan
这三种模式默认的是CONNECT_MODE,后面两种模式现在用到的不多,但按照Google的设计,后面可能会有很多的app会用到,比如利用热点来进行点位,这个应用其实这需要能够scan,并不需要链接热点。那我们接看这OperationalMode = CONNECT_MODE的流程,它直接transition 到DisconnectedState,如上图中的Figure 4,在transition到DisconnectedState之前,还会向WifiNative下reconnect的命令,用于重新连接上次连接但没有forget的AP,即开机后自动连上AP。
接着会进入mDisconnectedState状态,由于mDisconnectedState的父状态为mConnectedState状态,所以会先进入mConnectedState状态再进入mDisconnectedState状态,在这两个状态的enter方法中都没有什么特别的操作。
分析到这里,系统启动Wifi的初始化分析已经完成。
Android4.4(MT8685)源码WIFI--初始化2
标签:
原文地址:http://blog.csdn.net/u013467735/article/details/42493665