Wifi启动流程分析
因工作需要,对Android的Wifi模块做了些分析与跟踪,当前的源码版本是Android 4.4的,在Android 5以后已经发生了一些变化。
从Android的启动开始
进入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
进入到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 machinestart();
这里可以看到,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()方法:
@Overridepublic 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的初始化大致做完了,还有一些细节,留到以后再分析吧。
回到SystemServer
在本文开始的时候,有贴过一段代码,其中在初始化完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就启动了。
更多相关文章
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用
- python list.sort()根据多个关键字排序的方法实现
- Android之view重绘
- android事件分发机制
- AsyncTask源码剖析(API 23)
- 【转】Android(安卓)虚拟机安装APK文件方法
- 新书内容连载(2):Android(安卓)Activity的生命周期
- [Android]实现静默安装APK的两种方法