Android Wi-Fi源码分析之WifiService操作Wi-Fi(二):WifiStateMachine.java中的SUP_CONNECTION_EVENT分析
来源:互联网 发布:淘宝上的迪奥是真的吗 编辑:程序博客网 时间:2024/05/16 08:28
Wi-Fi源码分析之WifiService操作Wi-Fi(二)
一. SupplicantStartingState中的的processMessage方法分析
public boolean processMessage(Message message) { switch(message.what) { case WifiMonitor.SUP_CONNECTION_EVENT: if (DBG) log("Supplicant connection established"); setWifiState(WIFI_STATE_ENABLED);/*发送WIFI_STATE_CHANGED_ACTION广播*/ mSupplicantRestartCount = 0; /* Reset the supplicant state to indicate the supplicant * state is not known at this time */ mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);/*发送消息给SupplicantStateTracker状态机*/ /* Initialize data structures */ mLastBssid = null; mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; mLastSignalLevel = -1; /*设置本机IP地址*/ mWifiInfo.setMacAddress(mWifiNative.getMacAddress()); mWifiConfigStore.loadAndEnableAllNetworks(); initializeWpsDetails(); /*初始化WPS相关*/ /*发送SUPPLICANT_CONNECTION_CHANGE_ACTION广播*/ sendSupplicantConnectionChangedBroadcast(true); transitionTo(mDriverStartedState);/*转到DriverStartedState*/ 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; }
DriverStarted的父状态是SupplicantStarted(涉及到的HSM和各个状态层的关系以后再说), 所以transitionTo(mDriverStartedState)会导致DriverStarted和SupplicantStarted里的enter被调用.下面逐个分析.
二. SupplicantStartedState里的enter方法分析
class SupplicantStartedState extends State { @Override public void enter() { /* Wifi is available as long as we have a connection to supplicant */ mNetworkInfo.setIsAvailable(true); /*config_wifi_supplicant_scan_interval:控制扫描间隔,默认15000毫秒*/ int defaultInterval = mContext.getResources().getInteger( R.integer.config_wifi_supplicant_scan_interval); mSupplicantScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(), Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS, defaultInterval); /*向WPAS发送"SCAN_INTERVAL 扫描间隔时间"命令*/ mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000); } ...}
三. DriverStartedState里的enter方法分析
class DriverStartedState extends State { @Override public void enter() { mIsRunning = true; mInDelayedStop = false; mDelayedStopCounter++; updateBatteryWorkSource(null); /** * Enable bluetooth coexistence scan mode when bluetooth connection is active. * When this mode is on, some of the low-level scan parameters used by the * driver are changed to reduce interference with bluetooth * 蓝牙是运行在2.4GHz频段上,所以为了避免wlan和蓝牙互相干扰,下面这个函数将告知 * wlan driver蓝牙是否启用. 如果是 wlan芯片会做适当调整*/ mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); /* 设置国家代码和频段 * 其内部是通过发送消息的方式来出发WifiNative * setCountryCode和setBand函数被调用.在WifiNative中,这个两个函数都会发送形如 * "DRIVER XXX"命令给WPAS. DRIVER命令是Android平台特有的, 用于给wlan driver发送一些定制的命令. * hardware\broadcom\wlan\bcmdhd\wpa_supplicant_8_lib\driver_cmd_nl80211.c中有wlan driver的"DRIVER XXX"命令 */ setCountryCode(); setFrequencyBand(); /* initialize network state */ setNetworkDetailedState(DetailedState.DISCONNECTED); /*下面的三个函数都和WPAS中的"DRIVER XXX"命令有关*/ /* Remove any filtering on Multicast v6 at start */ mWifiNative.stopFilteringMulticastV6Packets(); /* Reset Multicast v4 filtering state */ if (mFilteringMulticastV4Packets.get()) { mWifiNative.startFilteringMulticastV4Packets(); } else { mWifiNative.stopFilteringMulticastV4Packets(); } 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();/*发送"RECONNECT"命令给wpas*/ // 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();/*发送"STATUS"命令给WPAS*/ transitionTo(mDisconnectedState);/*进入mDisconnectedState*/ } // We may have missed screen update at boot if (mScreenBroadcastReceived.get() == false) { PowerManager powerManager = (PowerManager)mContext.getSystemService( Context.POWER_SERVICE); handleScreenStateChanged(powerManager.isScreenOn()); } else { // Set the right suspend mode settings /*发送"DRIVER SETSUSPENDMODE"命令.该命令由Driver厂商提供的库来实现*/ mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0 && mUserWantsSuspendOpt.get()); } mWifiNative.setPowerSave(true);/*和P2P PowerSave有关*/ /*如果支持P2P,则通过mWifiP2pChannel向WifiP2p模块发送消息*/ if (mP2pSupported) { if (mOperationalMode == CONNECT_MODE) { mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P); } else { // P2P statemachine starts in disabled state, and is not enabled until // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to // keep it disabled. } } final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED); mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } @Override public boolean processMessage(Message message) { switch(message.what) { case CMD_START_SCAN: noteScanStart(message.arg1, (WorkSource) message.obj); startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP); break; case CMD_SET_BATCHED_SCAN: if (recordBatchedScanSettings(message.arg1, message.arg2, (Bundle)message.obj)) { startBatchedScan(); } break; case CMD_SET_COUNTRY_CODE: String country = (String) message.obj; if (DBG) log("set country code " + country); if (country != null) { country = country.toUpperCase(Locale.ROOT); if (mLastSetCountryCode == null || country.equals(mLastSetCountryCode) == false) { if (mWifiNative.setCountryCode(country)) { mLastSetCountryCode = country; } else { loge("Failed to set country code " + country); } } } break; case CMD_SET_FREQUENCY_BAND: int band = message.arg1; if (DBG) log("set frequency band " + band); if (mWifiNative.setBand(band)) { mFrequencyBand.set(band); // flush old data - like scan results mWifiNative.bssFlush(); //Fetch the latest scan results when frequency band is set startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP); } else { loge("Failed to set frequency band " + band); } break; case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: mBluetoothConnectionActive = (message.arg1 != BluetoothAdapter.STATE_DISCONNECTED); mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); break; case CMD_STOP_DRIVER: int mode = message.arg1; /* Already doing a delayed stop */ if (mInDelayedStop) { if (DBG) log("Already in delayed stop"); break; } /* disconnect right now, but leave the driver running for a bit */ mWifiConfigStore.disableAllNetworks(); mInDelayedStop = true; mDelayedStopCounter++; if (DBG) log("Delayed stop message " + mDelayedStopCounter); /* send regular delayed shut down */ Intent driverStopIntent = new Intent(ACTION_DELAYED_DRIVER_STOP, null); driverStopIntent.putExtra(DELAYED_STOP_COUNTER, mDelayedStopCounter); mDriverStopIntent = PendingIntent.getBroadcast(mContext, DRIVER_STOP_REQUEST, driverStopIntent, PendingIntent.FLAG_UPDATE_CURRENT); mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + mDriverStopDelayMs, mDriverStopIntent); break; case CMD_START_DRIVER: if (mInDelayedStop) { mInDelayedStop = false; mDelayedStopCounter++; mAlarmManager.cancel(mDriverStopIntent); if (DBG) log("Delayed stop ignored due to start"); if (mOperationalMode == CONNECT_MODE) { mWifiConfigStore.enableAllNetworks(); } } break; case CMD_DELAYED_STOP_DRIVER: if (DBG) log("delayed stop " + message.arg1 + " " + mDelayedStopCounter); if (message.arg1 != mDelayedStopCounter) break; handleStopDriverCmd(); if (mP2pSupported) { transitionTo(mWaitForP2pDisableState); } else { transitionTo(mDriverStoppingState); } break; case CMD_START_PACKET_FILTERING: if (message.arg1 == MULTICAST_V6) { mWifiNative.startFilteringMulticastV6Packets(); } else if (message.arg1 == MULTICAST_V4) { mWifiNative.startFilteringMulticastV4Packets(); } else { loge("Illegal arugments to CMD_START_PACKET_FILTERING"); } break; case CMD_STOP_PACKET_FILTERING: if (message.arg1 == MULTICAST_V6) { mWifiNative.stopFilteringMulticastV6Packets(); } else if (message.arg1 == MULTICAST_V4) { mWifiNative.stopFilteringMulticastV4Packets(); } else { loge("Illegal arugments to CMD_STOP_PACKET_FILTERING"); } break; case CMD_SET_SUSPEND_OPT_ENABLED: if (message.arg1 == 1) { setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); mSuspendWakeLock.release(); } else { setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); } break; case CMD_SET_HIGH_PERF_MODE: if (message.arg1 == 1) { setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false); } else { setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); } break; case CMD_ENABLE_TDLS: if (message.obj != null) { String remoteAddress = (String) message.obj; boolean enable = (message.arg1 == 1); mWifiNative.startTdls(remoteAddress, enable); } break; default: return NOT_HANDLED; } return HANDLED; } @Override public void exit() { mIsRunning = false; updateBatteryWorkSource(null); mScanResults = new ArrayList<ScanResult>(); stopBatchedScan(); final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); noteScanEnd(); // wrap up any pending request. mLastSetCountryCode = null; } }
WifiStateMachine将转入DisconnectedState. 由于DisconnectedState的父状态是ConnectModeState, 所以它的enter函数没有做任何有意义的工作.
四. 分析DisconnectedState中的enter方法
public void enter() { // We dont scan frequently if this is a temporary disconnect // due to p2p if (mTemporarilyDisconnectWifi) { mWifiP2pChannel.sendMessage(WifiP2pService.DISCONNECT_WIFI_RESPONSE); return; } mFrameworkScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(), Settings.Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS, mDefaultFrameworkScanIntervalMs); /* * We initiate background scanning if it is enabled, otherwise we * initiate an infrequent scan that wakes up the device to ensure * a user connects to an access point on the move * 当系统支持后台扫描时,如果手机屏幕关闭,则设置mEnableBackgroundScan为true启动后台扫描 */ if (mEnableBackgroundScan) { /* If a regular scan result is pending, do not initiate background * scan until the scan results are returned. This is needed because * initiating a background scan will cancel the regular scan and * scan results will not be returned until background scanning is * cleared * mScanResultIsPending用于表示WifiService是否在等待普通扫描的结果. * 因为启动后台扫描的时候会取消上一次扫描的请求,所以如果mScanResultIsPending * 为ture的话,就先不启用后台扫描. */ if (!mScanResultIsPending) { mWifiNative.enableBackgroundScan(true); } } else { /*设置定时扫描任务.到时间后,AlarmManager将发送一个"ACTION_START_SCAN"Intent * 而WifiStateMachine对Intent的处理就是调用startScan函数*/ setScanAlarm(true); } /** * If we have no networks saved, the supplicant stops doing the periodic scan. * The scans are useful to notify the user of the presence of an open network. * Note that these are not wake up scans. * 如果当前没有P2P连接,并且没有之前保存的AP信息,则发送CMD_NO_NETWORKS_PERIODIC_SCAN消息出发扫描 */ if (!mP2pConnected.get() && mWifiConfigStore.getConfiguredNetworks().size() == 0) { sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs); } }
阅读全文
0 0
- Android Wi-Fi源码分析之WifiService操作Wi-Fi(二):WifiStateMachine.java中的SUP_CONNECTION_EVENT分析
- Android Wi-Fi源码分析之WifiService操作Wi-Fi(一):分析Wifi.c中的wifi_load_driver()函数
- Android Wi-Fi WifiStateMachine解析
- Android Wi-Fi源码分析之wpa_supplicant初始化(二):wpa_supplicant_init中的三个关键点
- Android Wi-Fi源码分析之wpa_supplicant初始化(一)
- android Wi-Fi集成之分析
- Wi-Fi scan 分析
- Android Wi-Fi WifiMonitor分析(Android 7.0)
- Android N Wi-Fi 启动流程分析
- Android N Wi-Fi 扫描流程分析
- Android Wi-Fi源码分析之wpa_supplicant初始化(三):wpa_supplicant_add_iface函数分析
- Android Wi-Fi源码分析之wpa_supplicant初始化(四):wpa_supplicant_init_iface函数分析
- Android Wi-Fi基本操作
- Android Wi-Fi基本操作
- Android Wi-Fi 系统源码wifiSettings源码分析(Android 5.1 Base)
- ANdroid Wi-Fi 移植
- Android Wi-Fi wifi scan流程分析(Android 7.0)
- Android Wi-Fi connect & auto connect流程分析(Android 7.0)
- C++学习(33)
- Angular 中The “@angular/compiler-cli” package was not properly installed
- 简单幻灯片 demo
- Java的设计模式-----备忘录模式
- 程序猿,一个你不该犯的美丽错误...
- Android Wi-Fi源码分析之WifiService操作Wi-Fi(二):WifiStateMachine.java中的SUP_CONNECTION_EVENT分析
- 机器学习CoreML库
- eclipse启动报错java.lang.IllegalStateException: LifecycleProcessor not initialized
- 蓝桥杯 ALGO-84 算法训练 大小写转换
- Ubuntu14.04虚拟机中安装运行ROS操作系统
- 蓝桥杯 ALGO-81 算法训练 动态数组使用
- c++ 判断字符串只包含字母、数字、汉字 bool StringUtils::CheckName(const char * iName){ bool result=false; if(strle
- windows下rabbitmq环境搭建
- gdb调试器的使用方法小结,转载版