Android4.4(MT8685)源码WIFI--启动
系统启动时,会在SystemServer中创建一个WifiService的对象,并把这个对象保存在系统服务中
wifi = new WifiService(context); ServiceManager.addService(Context.WIFI_SERVICE, wifi);
看看WiFiService的构造方法
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(); }
这里初始化了一个WifiStateMachine和一个WifiController,并且调用了WifiController 的start方法,WifiController 继承至StateMachine状态机,这个start方法是父类的方法,表示启动一个状态机。我们先来看看WifiController这个状态机的构造方法
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); Log.e("dd","mStaDisabledWithScanState"); } else { setInitialState(mApStaDisabledState); Log.e("dd","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); }
这里参数service就是WifiService,并且通过service得到了WifiService中的WifiStateMachine对象,然后添加了一些状态对象,设置了初始状态,调用start方法后,WifiController首先进入mDefaultState状态,然后进入mApStaDisabledState状态,此时,WifiController状态机的状态为mApStaDisabledState状态。
让我们回到WifiService的构造方法中,倒数第二行有个registerForBroadcasts方法
private void registerForBroadcasts() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_SCREEN_ON); intentFilter.addAction(Intent.ACTION_USER_PRESENT); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); mContext.registerReceiver(mReceiver, intentFilter); }这个方法注册了一个广播,那我们看看接收到注册的这些action后,会有哪些处理
private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); SXlog.d(TAG, "onReceive, action:" + action); if (action.equals(Intent.ACTION_SCREEN_ON)) { mWifiController.sendMessage(CMD_SCREEN_ON); } else if (action.equals(Intent.ACTION_USER_PRESENT)) { mWifiController.sendMessage(CMD_USER_PRESENT); } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { mWifiController.sendMessage(CMD_SCREEN_OFF); } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { int pluggedType = intent.getIntExtra("plugged", 0); mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null); } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.STATE_DISCONNECTED); mWifiStateMachine.sendBluetoothAdapterStateChange(state); } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) { boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false); mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0); } } };当接收到的广播为ACTION_SCREEN_ON时,利用mWifiController对象发送一个CMD_SCREEN_ON消息,此时,mWifiController状态机的状态为mApStaDisabledState状态,我们看看这个状态实现类的processMessage方法
@Override public boolean processMessage(Message msg) { SXlog.d(TAG, getName() + msg.toString() + "\n"); switch (msg.what) { case CMD_WIFI_TOGGLED: case CMD_AIRPLANE_TOGGLED: Log.e("dd","1"); ///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","4"); 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; case CMD_SCAN_ALWAYS_MODE_CHANGED: if (mSettingsStore.isScanAlwaysAvailable()) { transitionTo(mStaDisabledWithScanState); } break; case CMD_SET_AP: if (msg.arg1 == 1) { mWifiStateMachine.setHostApRunning((WifiConfiguration) msg.obj, true); transitionTo(mApEnabledState); } break; case CMD_DEFERRED_TOGGLE: if (msg.arg1 != mDeferredEnableSerialNumber) { log("DEFERRED_TOGGLE ignored due to serial mismatch"); break; } log("DEFERRED_TOGGLE handled"); sendMessage((Message)(msg.obj)); break; default: return NOT_HANDLED; } return HANDLED; }
注意,这里没有处理CMD_SCREEN_ON消息,根据状态机的机制,子状态没处理的消息,将由父状态处理,mApStaDisabledState的父状态为mDefaultState状态,看看它的processMessage方法
@Override public boolean processMessage(Message msg) { SXlog.d(TAG, getName() + msg.toString() + "\n"); switch (msg.what) { case CMD_SCREEN_ON: mAlarmManager.cancel(mIdleIntent); mScreenOff = false; mDeviceIdle = false; Log.e("dd","mDeviceIdle = false;"); ///M: @{ mWifiStateMachine.setDeviceIdle(mDeviceIdle); ///@} updateBatteryWorkSource(); break; case CMD_SCREEN_OFF: mScreenOff = true; /* * Set a timer to put Wi-Fi to sleep, but only if the screen is off * AND the "stay on while plugged in" setting doesn't match the * current power conditions (i.e, not plugged in, plugged in to USB, * or plugged in to AC). */ if (!shouldWifiStayAwake(mPluggedType)) { //Delayed shutdown if wifi is connected if (mNetworkInfo.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) { if (DBG) Slog.d(TAG, "set idle timer: " + mIdleMillis + " ms"); ///M: modify to use Exact alarm for accuracy mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + mIdleMillis, mIdleIntent); } else { sendMessage(CMD_DEVICE_IDLE); } } break; case CMD_DEVICE_IDLE: mDeviceIdle = true; ///M: @{ mWifiStateMachine.setDeviceIdle(mDeviceIdle); ///@} updateBatteryWorkSource(); break; case CMD_BATTERY_CHANGED: /* * Set a timer to put Wi-Fi to sleep, but only if the screen is off * AND we are transitioning from a state in which the device was supposed * to stay awake to a state in which it is not supposed to stay awake. * If "stay awake" state is not changing, we do nothing, to avoid resetting * the already-set timer. */ int pluggedType = msg.arg1; if (DBG) Slog.d(TAG, "battery changed pluggedType: " + pluggedType); if (mScreenOff && shouldWifiStayAwake(mPluggedType) && !shouldWifiStayAwake(pluggedType)) { long triggerTime = System.currentTimeMillis() + mIdleMillis; if (DBG) Slog.d(TAG, "set idle timer for " + mIdleMillis + "ms"); mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent); } mPluggedType = pluggedType; break; case CMD_SET_AP: case CMD_SCAN_ALWAYS_MODE_CHANGED: case CMD_LOCKS_CHANGED: case CMD_WIFI_TOGGLED: case CMD_AIRPLANE_TOGGLED: case CMD_EMERGENCY_MODE_CHANGED: break; case CMD_USER_PRESENT: mFirstUserSignOnSeen = true; break; case CMD_DEFERRED_TOGGLE: log("DEFERRED_TOGGLE ignored due to state change"); break; default: throw new RuntimeException("WifiController.handleMessage " + msg.what); } return HANDLED; } }
果然,这里有处理CMD_SCREEN_ON消息,这里要注意的是
mDeviceIdle = false;稍后我们会用到这个flag,再一次回到WifiService的构造方法,其中有这么一段代码
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));
这里注册了一个捕捉ACTION_AIRPLANE_MODE_CHANGED的广播,接收到这个广播后,通过mWifiController发送一个CMD_AIRPLANE_TOGGLED的消息,来看看接收到这个消息的地方,还是在WifiController的当前状态mApStaDisabledState实现类的 processMessage方法中
@Override public boolean processMessage(Message msg) { SXlog.d(TAG, getName() + msg.toString() + "\n"); switch (msg.what) { case CMD_WIFI_TOGGLED: case CMD_AIRPLANE_TOGGLED: Log.e("dd","1"); ///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","4"); 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; case CMD_SCAN_ALWAYS_MODE_CHANGED: if (mSettingsStore.isScanAlwaysAvailable()) { transitionTo(mStaDisabledWithScanState); } break; case CMD_SET_AP: if (msg.arg1 == 1) { mWifiStateMachine.setHostApRunning((WifiConfiguration) msg.obj, true); transitionTo(mApEnabledState); } break; case CMD_DEFERRED_TOGGLE: if (msg.arg1 != mDeferredEnableSerialNumber) { log("DEFERRED_TOGGLE ignored due to serial mismatch"); break; } log("DEFERRED_TOGGLE handled"); sendMessage((Message)(msg.obj)); break; default: return NOT_HANDLED; } return HANDLED; }
当系统Wifi为开时,并且mDeviceIdle为false时,会把当前状态转换为mDeviceActiveState状态,mDeviceActiveState的父状态为mStaEnabledState状态,所以会先进入mStaEnabledState然后进入mDeviceActiveState状态,我们看看mStaEnabledState状态的实现类的enter方法
@Override public void enter() { Log.e("dd","StaEnabledState"); if (DBG) log(getName() + "\n"); mWifiStateMachine.setSupplicantRunning(true); }
这里调用了WifiService中的WifiStateMachine对象的setSupplicantRunning方法
public void setSupplicantRunning(boolean enable) { if (enable) { sendMessage(CMD_START_SUPPLICANT); } else { sendMessage(CMD_STOP_SUPPLICANT); } }
当参数为true时,发送一个CMD_START_SUPPLICANT消息,那么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);
初始状态为mInitialState,看看它的实现类的processMessage方法
@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; case CMD_START_AP: if (mWifiNative.loadDriver()) { setWifiApState(WIFI_AP_STATE_ENABLING); transitionTo(mSoftApStartingState); } else { loge("Failed to load driver for softap"); } ///M: for Hotknot, enable wifi for p2p, sta mode should not connect@{ case WifiManager.SET_WIFI_DISCONNECT: if(message.arg1 == 1){ mHotknotConnected.set(true); }else{ mHotknotConnected.set(false); } sendMessage(M_CMD_UPDATE_BGSCAN); break; ///@} default: return NOT_HANDLED; } return HANDLED; }
接收到CMD_START_SUPPLICANT消息后,首先会调用mWifiNative的loadDriver方法,loadDriver是一个本地方法,其作用是加载相应的Wifi驱动,如果驱动加载成功,会调用mWifiMonitor的startMonitoring方法,并且把当前的 状态转为mSupplicantStartingState状态。我们来看看mWifiMonitor这个对象,mWifiMonitor是一个WifiMonitor对象,它负责从wpa_supplicant接收消息,运行在一个独立的线程中。看看构造方法
public WifiMonitor(StateMachine wifiStateMachine, WifiNative wifiNative) { if (DBG) Log.d(TAG, "Creating WifiMonitor"); mWifiNative = wifiNative; mInterfaceName = wifiNative.mInterfaceName; mWifiStateMachine = wifiStateMachine; mMonitoring = false; WifiMonitorSingleton.getMonitor().registerInterfaceMonitor(mInterfaceName, this); }
这里传入了StateMachine对象和WifiNative对象,接着我们看看startMonitoring方法
public void startMonitoring() { WifiMonitorSingleton.getMonitor().startMonitoring(mInterfaceName); }这里调用WifiMonitor内部类WifiMonitorSingleton的startMonitoring方法
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; } } } }
这里会启动一个MonitorThread线程,看看这个线程的构造方法
public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) { super("WifiMonitor"); mWifiNative = wifiNative; mWifiMonitorSingleton = wifiMonitorSingleton; }
没做什么,再看run方法
public void run() { //noinspection InfiniteLoopStatement for (;;) { String eventStr = mWifiNative.waitForEvent(); // Skip logging the common but mostly uninteresting scan-results event if (DBG && eventStr.indexOf(SCAN_RESULTS_STR) == -1) { Log.d(TAG, "Event [" + eventStr + "]"); } String iface = "p2p0"; WifiMonitor m = null; mStateMachine = null; if (eventStr.startsWith("IFNAME=")) { int space = eventStr.indexOf(' '); if (space != -1) { iface = eventStr.substring(7,space); Log.d(TAG, "iface " + iface); m = mWifiMonitorSingleton.getMonitor(iface); if(m==null)Log.d(TAG, "hcan get mm " + iface); if (m == null && iface.startsWith("p2p-")) { // p2p interfaces are created dynamically, but we have // only one P2p state machine monitoring all of them; look // for it explicitly, and send messages there .. m = mWifiMonitorSingleton.getMonitor("p2p0"); } eventStr = eventStr.substring(space + 1); } } else { ///M: if ap0 exist, it could be hotspot event m = mWifiMonitorSingleton.getMonitor("ap0"); if(m!=null){ if(m.mMonitoring){ //we find hotspot active }else{ //try p2p0 m = mWifiMonitorSingleton.getMonitor("p2p0"); } }else{ // events without prefix belong to p2p0 monitor m = mWifiMonitorSingleton.getMonitor("p2p0"); } } if (m != null) { if (m.mMonitoring) { mStateMachine = m.mWifiStateMachine; } else { if (DBG) Log.d(TAG, "Dropping event because monitor (" + iface + ") is stopped"); continue; } } if (mStateMachine != null) { if (dispatchEvent(eventStr, m.mInterfaceName)) { //M: when dispatchEvent=true means break from waitForEvent //M: for hotspot clear hotspot data if(m.mInterfaceName.equals("ap0")){ m.mMonitoring =false; mWifiNative.closeSupplicantConnection(); Log.d(TAG, "ap0 get TEMINATING 1"); } break; } } else { if (DBG) Log.d(TAG, "Sending to all monitors because there's no interface id"); boolean done = false; Iterator<Map.Entry<String, WifiMonitor>> it = mWifiMonitorSingleton.mIfaceMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, WifiMonitor> e = it.next(); m = e.getValue(); mStateMachine = m.mWifiStateMachine; if (dispatchEvent(eventStr,null)) { done = true; } } if (done) { //M: for hotspot clear hotspot data if(m.mInterfaceName.equals("ap0")){ m.mMonitoring =false; mWifiNative.closeSupplicantConnection(); Log.d(TAG, "ap0 get TEMINATING 2"); } // After this thread terminates, we'll no longer // be connected to the supplicant if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events"); mWifiMonitorSingleton.mConnected = false; break; } } } }
这里调用了mWifiNative的waitForEvent方法,这个方法通过jni调用本地方法读取wpa_supplicant的消息,接着转发出去
while (it.hasNext()) { Map.Entry<String, WifiMonitor> e = it.next(); m = e.getValue(); mStateMachine = m.mWifiStateMachine; if (dispatchEvent(eventStr,null)) { done = true; } }
看看dispatchEvent方法
/* @return true if the event was supplicant disconnection */ private boolean dispatchEvent(String eventStr, String iface) { if (!eventStr.startsWith(EVENT_PREFIX_STR)) { if ((eventStr.startsWith(WPA_EVENT_PREFIX_STR) && 0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR)) ///M:@{ || (eventStr.startsWith(AUTHENTICATION_TIMEOUT_PREFIX_STR) && 0 < eventStr.indexOf(AUTHENTICATION_TIMEOUT_STR))) { ///@} mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT); } else if (eventStr.startsWith(WPS_SUCCESS_STR)) { mStateMachine.sendMessage(WPS_SUCCESS_EVENT); } else if (eventStr.startsWith(WPS_FAIL_STR)) { handleWpsFailEvent(eventStr); } else if (eventStr.startsWith(WPS_OVERLAP_STR)) { mStateMachine.sendMessage(WPS_OVERLAP_EVENT); } else if (eventStr.startsWith(WPS_TIMEOUT_STR)) { mStateMachine.sendMessage(WPS_TIMEOUT_EVENT); } else if (eventStr.startsWith(P2P_EVENT_PREFIX_STR)) { handleP2pEvents(eventStr); } else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) { handleHostApEvents(eventStr, iface); ///M:@{ } else if (eventStr.startsWith(EAP_FAST_NEW_PAC_UPDATED)) { mStateMachine.sendMessage(NEW_PAC_UPDATED_EVENT); ///M: whole chip reset fail } else if (eventStr.startsWith(WHOLE_CHIP_RESET_FAIL_STRING)){ mStateMachine.sendMessage(WHOLE_CHIP_RESET_FAIL_EVENT); /** M: NFC Float II @{ */ } else if (eventStr.startsWith(WPS_ER_ENROLLEE_ADD_STR)) { mStateMachine.sendMessage(WPS_ER_ENROLLEE_ADD_EVENT, eventStr); } else if (eventStr.startsWith(WPS_ER_AP_ADD_STR)) { mStateMachine.sendMessage(WPS_ER_AP_ADD_EVENT, eventStr); /** } */ } ///@} else { if (DBG) Log.w(TAG, "couldn't identify event type - " + eventStr); } return false; } String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR); int nameEnd = eventName.indexOf(' '); if (nameEnd != -1) eventName = eventName.substring(0, nameEnd); if (eventName.length() == 0) { if (DBG) Log.i(TAG, "Received wpa_supplicant event with empty event name"); return false; } /* * Map event name into event enum */ int event; if (eventName.equals(CONNECTED_STR)) event = CONNECTED; else if (eventName.equals(DISCONNECTED_STR)) { event = DISCONNECTED; ///M: add handleP2pEvents(eventStr); } else if (eventName.equals(STATE_CHANGE_STR)) event = STATE_CHANGE; else if (eventName.equals(SCAN_RESULTS_STR)) event = SCAN_RESULTS; else if (eventName.equals(LINK_SPEED_STR)) event = LINK_SPEED; else if (eventName.equals(TERMINATING_STR)) event = TERMINATING; else if (eventName.equals(DRIVER_STATE_STR)) event = DRIVER_STATE; else if (eventName.equals(EAP_FAILURE_STR)) event = EAP_FAILURE; else if (eventName.equals(ASSOC_REJECT_STR)) event = ASSOC_REJECT; ///M: @{ else if (eventName.equals(WAPI_NO_CERTIFICATION_STRING)) event = NO_CERTIFICATION; ///@} else event = UNKNOWN; String eventData = eventStr; if (event == DRIVER_STATE || event == LINK_SPEED) eventData = eventData.split(" ")[1]; else if (event == STATE_CHANGE || event == EAP_FAILURE) { int ind = eventStr.indexOf(" "); if (ind != -1) { eventData = eventStr.substring(ind + 1); } } else { int ind = eventStr.indexOf(" - "); if (ind != -1) { eventData = eventStr.substring(ind + 3); } } if (event == STATE_CHANGE) { handleSupplicantStateChange(eventData); } else if (event == DRIVER_STATE) { handleDriverEvent(eventData); } else if (event == TERMINATING) { Log.d(TAG, "event == TERMINATING " ); /** * Close the supplicant connection if we see * too many recv errors */ if (eventData.startsWith(WPA_RECV_ERROR_STR)) { if (++mRecvErrors > MAX_RECV_ERRORS) { if (DBG) { Log.d(TAG, "too many recv errors, closing connection"); } } else { return false; } } // notify and exit if(iface!=null && !iface.equals("ap0")){ mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT); } Log.d(TAG, "Exit because of receiving terminating for " + getName() + ", id:" + getId()); return true; } else if (event == EAP_FAILURE) { if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) { mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT); } } else if (event == ASSOC_REJECT) { mStateMachine.sendMessage(ASSOCIATION_REJECTION_EVENT); } else { handleEvent(event, eventData); } mRecvErrors = 0; return false; }
经过一系列处理调用handleEvent方法
void handleEvent(int event, String remainder) { switch (event) { case DISCONNECTED: handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED, remainder); break; case CONNECTED: handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder); break; case SCAN_RESULTS: mStateMachine.sendMessage(SCAN_RESULTS_EVENT); break; ///M: @{ case NO_CERTIFICATION: mStateMachine.sendMessage(WAPI_NO_CERTIFICATION_EVENT); break; ///@} case UNKNOWN: break; } }
以SCAN_RESULTS_EVENT为例,状态机发送一个SCAN_RESULTS_EVENT消息,这个状态机是WifiStateMachine对象,WifiStateMachine当前的状态为SupplicantStartedState(中间的过程暂时忽略),看看processMessage方法相关代码
case WifiMonitor.SCAN_RESULTS_EVENT: setScanResults(); if (mWifiFwkExt.hasCustomizedAutoConnect()) { mShowReselectDialog = false; Xlog.d(TAG, "SCAN_RESULTS_EVENT, mScanForWeakSignal:" + mScanForWeakSignal); if (mScanForWeakSignal) { showReselectionDialog(); } mDisconnectNetworkId = INVALID_NETWORK_ID; } sendScanResultsAvailableBroadcast(); mScanResultIsPending = false; break;
这里会调用sendScanResultsAvailableBroadcast发送广播,把扫描到的Wifi热点信息发送给广播接收者
private void sendScanResultsAvailableBroadcast() { noteScanEnd(); Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(IWifiFwkExt.EXTRA_SHOW_RESELECT_DIALOG_FLAG, mShowReselectDialog); mContext.sendBroadcastAsUser(intent, UserHandle.ALL); }
至此,Wifi启动的一个大概流程就先分析到这里!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。