Android4.4 WIFI开机启动流程详析
来源:互联网 发布:java区块链开源项目 编辑:程序博客网 时间:2024/04/30 01:12
之前看过android4.0版本的wifi启动流程,对比android4.4的版本启动还是有不少出入,下面将android4.4的wifi相关部分启动代码流程做如下分析:
软件平台:Android4.4
硬件平台:MTK6572
WifiService作为wifi的主service,也是从SystemServer的initAndLoop中启动:
public void initAndLoop() { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis()); /// M: BOOTPROF @{ mMTPROF_disable = "1".equals(SystemProperties.get("ro.mtprof.disable")); addBootEvent(new String("Android:SysServerInit_START")); /// @} Looper.prepareMainLooper(); ...... 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); } ......}根据代码我们得知调到了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,这个构造方法我们后续再做详细说明,之后创建了wifiThread线程,并调用了start方法开始执行此线程(实则是开启了Looper模式,java中每一个thread只能有一个Looper,一个Looper可以包含多个Handler和MQ,每一个Handler在添加到线程的Looper中时也都有自己相应的MQ,这样线程中的MQ就会按顺序的处理消息然后发送给与之绑定的Handler去处理msg),紧接着是把ClientHandler,WifiStateMachineHandler都添加到Looper中,后续实例化一个WifiController,并调用start,为什么它也有start?因为它继承自StateMachine。
接下来,WifiController的构造方法:
WifiController(Context context, WifiService service, Looper looper) { super(TAG, looper); mContext = context; mWifiStateMachine = service.mWifiStateMachine; ...... 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中实例化的状态机赋值给本地状态机,然后调用addState方法添加了一系列的父子状态机状态,根据后续的if-else逻辑我们不难发现状态机被初始化为mApStaDisabledState状态(记住这是状态机第一个暂留的状态)。WifiController先说明到此,这一步主要的就是第一个初始化的状态机状态。
回过头我们继续看WifiService构造方法中的registerForBroadcast()方法:
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_SCREEN_ON事件的广播侦听,在收到该广播之后:
if (action.equals(Intent.ACTION_SCREEN_ON)) { mWifiController.sendMessage(CMD_SCREEN_ON);
向WifiController发送了CMD_SCREEN_ON的MSG,然后我们回到WifiController,在上一步将WifiController的时候,我们记住了一个状态:mApStaDisabledState,该MSG就是发送给了这个状态的processMessage()方法,然并卵,我们在此方法中并未看到对CMD_SCREEN_ON的处理,根据状态机的特点,我们看该状态的父状态有没有做处理。父状态为DefaultState,这里边果然有处理该消息的逻辑:
case CMD_SCREEN_ON: mAlarmManager.cancel(mIdleIntent); mScreenOff = false; mDeviceIdle = false; ///M: @{ mWifiStateMachine.setDeviceIdle(mDeviceIdle); ///@} updateBatteryWorkSource(); break;
这里边我们着重记住一个变量的赋值,mDeviceIdle = false;后面我们继续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方法中:
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) { 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;注意当中对mDeviceIdle的判断,之前确定了该值为false,因此这个时候涉及到一个状态机状态的切换,切换至mDeviceActiveState,首先是进入该状态机的父状态机,StaEnabledState,此状态的enter方法如下:
@Override public void enter() { if (DBG) log(getName() + "\n"); mWifiStateMachine.setSupplicantRunning(true); }
调用setSupplicantRunning(true),
public void setSupplicantRunning(boolean enable) { if (enable) { sendMessage(CMD_START_SUPPLICANT); } else { sendMessage(CMD_STOP_SUPPLICANT); } }发出了一个CMD_START_SUPPLICANT的MSG,那么当前WifiStateMachine处于什么状态呢?我们切看一开始滞后解析的WifiStateMachine构造方法,状态机最初始暂存的一个状态是
setInitialState(mInitialState);也就是InitialState状态的processMessage处理CMD_START_SUPPLICANT消息,
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;调用WifiNative的loadDriver方法,该方法定义在frameworks/base/core/jni/android_net_wifi_WifiNative.cpp中:
static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject){ ///M:@{ g_pItemListMutex = new pthread_mutex_t; if (NULL == g_pItemListMutex) { XLOGE("Failed to allocate memory for g_pItemListMutex!"); return JNI_FALSE; } pthread_mutex_init(g_pItemListMutex, NULL); g_pCurrentSSID = new String8(); if (NULL == g_pCurrentSSID) { XLOGE("Failed to allocate memory for g_pCurrentSSID!"); return JNI_FALSE; } char dbg[PROPERTY_VALUE_MAX] = {0}; if (property_get("wifi.jni.dbg", dbg, NULL) && strcmp(dbg, "true") == 0) { DBG = true; } else { DBG = false; } ///@} return (::wifi_load_driver() == 0); }最后调到了hardware层的wifi.c中的接口:hardware/libhardware_legacy/wifi/wifi.c
int wifi_load_driver(){#ifdef WIFI_DRIVER_MODULE_PATH char driver_status[PROPERTY_VALUE_MAX]; int count = 100; /* wait at most 20 seconds for completion */ if (is_wifi_driver_loaded()) { return 0; } if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1; if (strcmp(FIRMWARE_LOADER,"") == 0) { /* usleep(WIFI_DRIVER_LOADER_DELAY); */ property_set(DRIVER_PROP_NAME, "ok"); } else { property_set("ctl.start", FIRMWARE_LOADER); } sched_yield(); while (count-- > 0) { if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) { if (strcmp(driver_status, "ok") == 0) return 0; else if (strcmp(DRIVER_PROP_NAME, "failed") == 0) { wifi_unload_driver(); return -1; } } usleep(200000); } property_set(DRIVER_PROP_NAME, "timeout"); wifi_unload_driver(); return -1;#else ALOGD("enter -->%s\n, uid=%d, gid=%d", __func__, getuid(), getgid()); property_set(DRIVER_PROP_NAME, "ok"); /*fix wifi_send_commadn bug*/ wifi_init_sync(&wifi_sync); return 0;#endif}调用insmod方法去loading相应path的ko文件,成功的话设置相应的property,返回0,失败的话返回-1。
回到WifiStateMachine的CMD_START_SUPPLICANT的处理,在load完driver之后,会开启wpa服务。
mWifiMonitor.killSupplicant(mP2pSupported); if(mWifiNative.startSupplicant(mP2pSupported)) { if (DBG) log("Supplicant start successful"); mWifiMonitor.startMonitoring(); transitionTo(mSupplicantStartingState); } else { loge("Failed to start supplicant!"); }调用WifiNative的接口,间接调用hardware层的wifi_start_supplicant方法,该方法在此不再赘述,只是通过property设置开启spa_supplicant service。之后是调用WifiMonitor的startMonitoring方法,并把状态机切换至mSupplicantStartingState状态:
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; } } } }第一次执行,mConnected为false,走else通路,调用WifiNative.connectToSupplicant()方法,继而到hal层wifi_connect_to_supplicant()方法,此方法最终调用到了 wpa层的代码:wpa_ctl_open打开了两个连接:ctrl_conn和monitor_conn。
后边开启一个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; } } } }这里调用了WifiNative的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 为例,状态机发送SCAN_RESULTS_EVENT消息,这个状态机为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()方法:
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); }至此,大体流程结束。。。
0 0
- Android4.4 WIFI开机启动流程详析
- android4.0 wifi启动流程
- android4.0.3 wifi 启动流程(一)
- Android4.0 wifi 启动流程 二
- Android4.0 wifi 启动流程3 之 wifi连接
- android4.4 wifi 扫描流程分析
- Android4.4 Activity启动流程
- Android4.4 systemui 启动流程
- [Android4.4]netd启动流程
- android4.0 WIFI的启动流程和状态机变化
- android4.0 WIFI的启动流程和状态机变化
- android4.0 WIFI的启动流程和状态机变化
- android4.0 开机启动
- Android4.4 Activity启动流程分析
- WIFI启动流程-NEW
- wifi 启动流程
- Wifi启动流程分析
- wifi启动流程
- 【模板】约瑟夫环
- Android Activity onCreate()方法重复执行
- BI进行中,重新设计改造质检数据管理系统(图文)
- Docker Compose—简化复杂应用的利器
- 315. Count of Smaller Numbers After Self
- Android4.4 WIFI开机启动流程详析
- PHP 变量作用域
- [JZSC2016 Part 2] 【NOIP2016提高A组模拟8.19】总结
- 文章记录
- 网关模式/网桥模式/旁路模式的区别
- c#中的ref和out
- 修改HISTSIZE和PS1提示
- C语言基本教程 第9课: 自定义数据结构
- 简单表单字段的获取