因工作需要,对Android的Wifi模块做了些分析与跟踪,当前的源码版本是Android 4.4的,在Android 5以后已经发生了一些变化。
进入Android的入口是SystemServer,在这里面注册了许多的Service。这里主要看与Wifi相关的服务。
try {
Slog.i(TAG, "Wi-Fi Service");
wifi = new WifiService(context);
ServiceManager.addService(Context.WIFI_SERVICE, wifi);
} catch (Throwable e) {
reportWtf("starting Wi-Fi Service", e);
}
try {
Slog.i(TAG, "Connectivity Service");
connectivity = new ConnectivityService(
context, networkManagement, networkStats, networkPolicy);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
networkStats.bindConnectivityManager(connectivity);
networkPolicy.bindConnectivityManager(connectivity);
wifiP2p.connectivityServiceReady();
wifi.checkAndStartWifi();
} catch (Throwable e) {
reportWtf("starting Connectivity Service", e);
}
上述代码中,初始化了wifiService,并把这两个对象加到ServiceManager上,接着又创建了ConnectivityService对象,然后通过创建的WiFiService对象调用wifi.checkAndStartWifi();用于初始化开机时的wifi状态。
进入到WifiService.java的构造方法中,路径:
/frameworks/base/services/java/com/android/server/wifi/WifiService.java
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) {
if (mSettingsStore.handleAirplaneModeToggled()) {
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();
}
这里可以看到,首先读取系统属性,获取系统wifi.interface,默认为wlan0。主要看这两句:
mWifiStateMachine =new WifiStateMachine(mContext,mInterfaceName);
mWifiStateMachine.enableRssiPolling(true);
可以看到,在实例化WifiService的时候,先创建了一个Wifi状态机对象,然后开始Rssi轮询。然后新建一个HandlerThread来处理所有的Message,并注册一些Broadcast的接收者。接着又创建了一个mWifiController 。(【注】:其实自己之前看到这里的时候也在想,为什么这么麻烦?先搞了一个Wifi状态机(哈哈,以前听到状态机,感觉感觉蛮高大上的样子),然后又弄了个WifiController又是干嘛的。)
其实,WifiStateMachine用于控制整个Wifi的开启、关闭、连接和断开等各个状态的切换,这个感觉还是比较复杂的,后面再说吧。不过还是先看看它的构造方法做了些什么:源码路径在:/frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java
这个构造方法太长了,截取一段比较关键的:
mWifiNative = new WifiNative(mInterfaceName);
mWifiConfigStore = new WifiConfigStore(context, mWifiNative);
mWifiMonitor = new WifiMonitor(this, mWifiNative);
mWifiInfo = new WifiInfo();
mSupplicantStateTracker = new SupplicantStateTracker(context, this, mWifiConfigStore, getHandler());
mLinkProperties = new LinkProperties();
mNetlinkLinkProperties = new LinkProperties();
这里初始化了一些对象,都是与wifi的控制相关的信息。
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);
setLogRecSize(2000);
setLogOnlyTransitions(false);
if (DBG) setDbg(true);
//start the state machine
start();
这里可以看到,WifiStateMachine在实例化的时候,往状态机中添加了许许多多的状态,在wifi连接与断开的整个流程中,都会与上述添加的状态息息相关。添加完这些状态后,先是设置了一下wifi状态机的最初始状态为InitialState。然后调用start()方法启动wifi状态机工作,这个start()方法的实现在WifiStateMachine的父类StateMachine中,所以状态机也叫层次状态机。
由上面的分析,知道了在WifiService初始化的时候,实例化了一个WifiStateMachine,然后由WifiStateMachine接管了整个Wifi运行时期各种状态变化的管理。
不过,在WifiService的构造方法中,还实例化了一个WifiController对象,这个又是在干嘛呢?来看看它在实例化的时候做了些什么:
/frameworks/base/services/java/com/android/server/wifi/WifiController.java
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);
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);
}
这段代码好长,感觉贴图上来好难看。。。
不过可以大致看到,在WifiService中把WifiStateMachine的实例传了进来。这里也注册了好几种状态,是的,WifiController也继承自StateMachine,并且在实例化的时候设置了初始状态。如下,当wifi被设置为一直可以扫描的话,初始状态会设置为mStaDisabledWithScanState,一般会走else分支。
if (mSettingsStore.isScanAlwaysAvailable()) {
setInitialState(mStaDisabledWithScanState);
} else {
setInitialState(mApStaDisabledState);
}
在WifiService中创建该实例后,立即调用了mWifiController.start();根据刚才对WiFiStateMachine的分析可知,这里调用的是状态机父类StateMachine中的start()方法。调用start方法后,WifiController首先进入mDefaultState状态,然后进入mApStaDisabledState状态(为什么呢?从addState(mApStaDisabledState, mDefaultState);可以看出,mDefaultState是mApStaDisabledState的父状态,执行的时候,会先进入父状态的enter(),然后再执行子状态。【层次状态机】),此时,WifiController状态机的状态为mApStaDisabledState状态,进入到该状态的enter()方法:
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(false);
// Supplicant can't restart right away, so not the time we switched off
mDisabledTimestamp = SystemClock.elapsedRealtime();
mDeferredEnableSerialNumber++;
mHaveDeferredEnable = false;
}
发现做了些配置,没有更多的动作,到这里WifiService的初始化大致做完了,还有一些细节,留到以后再分析吧。
在本文开始的时候,有贴过一段代码,其中在初始化完WifiService和ConnectivityService后,执行了如下代码:
wifi.checkAndStartWifi();
这句代码才开始真正从开机状态完成真正的wifi监测与打开的动作。
public void checkAndStartWifi() {
//检查WiFi是否需要使能
boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
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
// MStar Android Patch Begin
if (wifiEnabled) {
setWifiEnabled(wifiEnabled);
} else {
//如果Wifi本身没有启动,测试softap是否需要启动
boolean wifiApEnabled = mSettingsStore.isWifiApToggleEnabled();
if (wifiApEnabled) {
Slog.d(TAG, "wifi ap start with enabled");
setWifiApEnabled(null, wifiApEnabled);
} else {
Slog.d(TAG, "wifi ap start with disabled");
}
}
// MStar Android Patch End
mWifiWatchdogStateMachine = WifiWatchdogStateMachine.makeWifiWatchdogStateMachine(mContext);
}
上述实现WifiService.java中,首先来看这句:
boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
先读取系统上次关机时的wifi开关状态,如果该值为true,证明上次是打开的,那么执行如下代码:
setWifiEnabled(wifiEnabled);
来看这句代码的实现:
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;
}
关键是最后一句:mWifiController.sendMessage(CMD_WIFI_TOGGLED);
给WifiController发了个消息:CMD_WIFI_TOGGLED。又转到了WifiController中 :)
刚才前面已经分析过,当wifiController的初始化状态为:ApStaDisabledState。所以,当前这个消息将由该状态来处理,来看它的processMessage()方法:
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
case CMD_AIRPLANE_TOGGLED:
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) {
transitionTo(mDeviceActiveState);
} else {
checkLocksAndTransitionWhenDeviceIdle();
}
}
break;
....
default:
return NOT_HANDLED;
}
return HANDLED;
}
这里可以看到,当系统wifi打开,并且mDeviceIdle == false,则会执行状态转换:
transitionTo(mDeviceActiveState);
由addState(mDeviceActiveState, mStaEnabledState);
可知,mStaEnabledState是mDeviceActiveState的父状态,所以先执行其enter()方法,
class StaEnabledState extends State {
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(true);
}
...
}
这里执行了WifiStateMachine的setSupplicantRunning方法。
public void setSupplicantRunning(boolean enable) {
if (enable) {
sendMessage(CMD_START_SUPPLICANT);
} else {
sendMessage(CMD_STOP_SUPPLICANT);
}
}
可以看到,这里又发了消息:CMD_START_SUPPLICANT。前面分析WiFiStateMachine初始化的时候,已经说过,其初始化状态为InitialState,所以这个消息将由它的processMessage()方法来处理:
case CMD_START_SUPPLICANT:
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)) {
setWifiState(WIFI_STATE_ENABLING);
if (DBG) log("Supplicant start successful");
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
} else {
loge("Failed to start supplicant!");
}
} else {
loge("Failed to load driver");
}
break;
这一段代码还是比较关键的,可以看到首先通过mWifiNative.loadDriver()去加载驱动,当驱动加载成功后,重新加载固件:
mNwService.wifiFirmwareReload(mInterfaceName, "STA");
mNwService.setInterfaceDown(mInterfaceName)
...
setWifiState(WIFI_STATE_ENABLING);
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
...
做了一系列的配置操作,设置wifi状态为WIFI_STATE_ENABLING正在打开,开始监管startMonitoring(),最后把状态转移到mSupplicantStartingState。
看完父状态的操作,再来看mDeviceActiveState的enter方法:
class DeviceActiveState extends State {
@Override
public void enter() {
mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
mWifiStateMachine.setDriverStart(true);
mWifiStateMachine.setHighPerfModeEnabled(false);
}
...
}
可以看到,这里都是在通过wifi状态机去做一系列的操作,比如设置连接模式,启动driver等,来看看
mWifiStateMachine.setDriverStart(true);
看看它的实现:
public void setDriverStart(boolean enable) {
if (enable) {
sendMessage(CMD_START_DRIVER);
} else {
sendMessage(CMD_STOP_DRIVER);
}
}
这里由刚才分析的结果,WiFiStateMachine进入了mSupplicantStartingState状态,所以,这个消息将由它的方法去处理,再经过几次状态转换到SupplicantStartedState,driver就启动了。