WiFi扫描场景
WiFi扫描场景根据设备的屏幕状态、用户当前的活动以及网络环境的不同,而采用了不同的扫描策略。
1.「亮屏且在WiFi设置界面」:
当用户在亮屏状态下进入WiFi设置界面时,设备会进行固定扫描,扫描时间通常为10秒。这种扫描是为了快速获取当前可用的WiFi网络列表,供用户选择连接。
2.「亮屏且不在WiFi设置界面」:
在这种情况下,Android设备会采用二进制指数退避扫描策略。扫描间隔会根据一定的算法逐渐增长,最小间隔为20秒,最大间隔可能达到160秒。这种策略有助于平衡设备的能耗和WiFi扫描的效率。
3.「灭屏且有保存的网络」:如果设备处于灭屏状态,但之前有保存过WiFi网络,那么设备会根据当前的网络连接状态进行扫描。如果已连接到某个网络,则不会进行扫描;否则,设备会进行PNO(Preferred Network Offload)扫描,即只扫描已保存的网络。这种扫描的最小间隔为20秒,最大间隔为60秒。
4.无保存网络」:
在没有保存任何WiFi网络的情况下,设备会进行固定扫描,扫描间隔通常为5分钟。这种扫描的目的是为了通知用户周围存在可用的开放网络。
还有一些特殊场景下的WiFi扫描,例如:
「位置变化」:当用户携带设备移动到新的位置时,设备可能会自动触发WiFi扫描,以寻找并连接到新的可用网络。
「应用请求」:某些应用可能需要在后台请求WiFi扫描,以获取周围的网络信息或进行其他相关操作。在这种情况下,Android系统会根据应用的权限和策略来决定是否允许扫描。
亮屏且在WiFi设置界面
当设备处于亮屏状态且正在WiFi设置界面时,WiFi扫描的行为会更为活跃和精确。这是为了提供一个实时、准确的可用WiFi网络列表,以便能够方便地选择并连接到合适的网络。
- 「实时扫描」:当打开WiFi设置界面时,系统会立即启动一次WiFi扫描。这次扫描是实时的,会立即搜索并列出当前可用的WiFi网络。
- 「持续刷新」:一旦扫描开始,系统会持续刷新WiFi网络列表,以确保列出的网络是最新的。通过定期重新扫描或监听网络变化事件来实现的。
- 「网络信号强度显示」:在WiFi设置界面,除了列出网络名称(SSID)外,系统还会显示每个网络的信号强度。这有助于判断哪个网络的信号更好,从而做出更明智的连接选择。
- 「安全性标识」:对于每个列出的WiFi网络,系统还会显示其安全性信息(如开放网络、WPA2-PSK等)。这有助于了解网络的安全性,并决定是否信任并连接到该网络。
- 「用户交互」:在WiFi设置界面,可以进行多种操作,如点击某个网络进行连接、输入密码、忘记网络等。这些操作会触发相应的系统响应,如启动连接过程、验证密码等。
亮屏且在WiFi设置界面时设备会进行固定扫描,扫描时间通常为10秒。这种扫描是为了快速获取当前可用的WiFi网络列表,供用户选择连接。WIFI_RESCAN_INTERVAL_MS为 10 * 1000(10秒)。
//WifiTracker.java
public void handleMessage(Message message) {
if (message.what != MSG_SCAN) return;
if (mWifiManager.startScan()) {
mRetry = 0;
} else if (++mRetry >= 3) {
mRetry = 0;
if (mContext != null) {
Toast.makeText(mContext, R.string.wifi_fail_to_scan, Toast.LENGTH_LONG).show();
}
return;
}
sendEmptyMessageDelayed(MSG_SCAN, WIFI_RESCAN_INTERVAL_MS);
}
亮屏且不在WiFi设置界面
当设备的屏幕处于亮屏状态,但并不在WiFi设置界面时,WiFi扫描的行为会有所不同。在这种情况下,系统会根据一系列策略和算法来管理WiFi扫描,以平衡设备的能耗、性能和用户体验。
- 「减少扫描频率」:与在WiFi设置界面时相比,当不在该界面时,系统通常会减少WiFi扫描的频率。这是为了降低设备的能耗,并避免在不必要的情况下进行过多的网络搜索。
- 「二进制指数退避扫描」:为了进一步优化扫描行为,Android系统可能会采用二进制指数退避扫描策略。每次扫描之间的间隔会逐渐增加,基于一个退避算法。初始间隔可能较短,但随着连续扫描次数的增加,间隔会逐渐延长。这种策略有助于减少扫描的频繁性,同时能够保持对可用网络的检测能力。
- 「应用层请求」:尽管系统减少了自动扫描的频率,但应用程序仍然可以在后台请求WiFi扫描。例如,某些应用可能需要获取周围的网络信息以执行其功能。在这种情况下,系统会评估应用的权限和请求,并根据需要执行扫描。
- 「位置和网络变化触发」:如果设备的位置发生变化或检测到网络状态发生变化(例如,从移动数据切换到WiFi),系统可能会自动触发一次WiFi扫描。确保设备能够及时发现并连接到新的可用网络。
- 「用户手动触发」:尽管系统减少了自动扫描,仍然可以手动触发WiFi扫描。例如,可以通过下拉通知栏并点击“WiFi”图标来重新扫描可用网络。
亮屏且不在WiFi设置界面时扫描间隔会根据一定的算法逐渐增长,最小间隔为20秒,最大间隔可能达到160秒。
startConnectivityScan --> startPeriodicScan --> startPeriodicSingleScan
//WifiConnectivityManager.java
//扫描间隔定义
// Periodic scan interval in milli-seconds. This is the scan
// performed when screen is on.
public static final int PERIODIC_SCAN_INTERVAL_MS = 20 * 1000; // 20 seconds
// When screen is on and WiFi traffic is heavy, exponential backoff
// connectivity scans are scheduled. This constant defines the maximum
// scan interval in this scenario.
@VisibleForTesting
public static final int MAX_PERIODIC_SCAN_INTERVAL_MS = 160 * 1000; // 160 seconds
private void startConnectivityScan(boolean scanImmediately) {
// Always stop outstanding connecivity scan if there is any
stopConnectivityScan();
if (mWifiState != WIFI_STATE_CONNECTED && mWifiState != WIFI_STATE_DISCONNECTED) {
return;
}
if (mScreenOn) {
startPeriodicScan(scanImmediately);
} else {
if (mWifiState == WIFI_STATE_DISCONNECTED && !mPnoScanStarted) {
startDisconnectedPnoScan();
}
}
}
private void startPeriodicScan(boolean scanImmediately) {
mPnoScanListener.resetLowRssiNetworkRetryDelay();
if (scanImmediately) {
resetLastPeriodicSingleScanTimeStamp();
}
mPeriodicSingleScanInterval = PERIODIC_SCAN_INTERVAL_MS;
startPeriodicSingleScan();
}
// Start a single scan and set up the interval for next single scan.
private void startPeriodicSingleScan() {
long currentTimeStamp = mClock.getElapsedSinceBootMillis();
if (mLastPeriodicSingleScanTimeStamp != RESET_TIME_STAMP) {
long msSinceLastScan = currentTimeStamp - mLastPeriodicSingleScanTimeStamp;
if (msSinceLastScan < PERIODIC_SCAN_INTERVAL_MS) {
localLog("Last periodic single scan started " + msSinceLastScan + "ms ago, defer this new scan request.");
schedulePeriodicScanTimer(PERIODIC_SCAN_INTERVAL_MS - (int) msSinceLastScan);
return;
}
if (isScanNeeded) {
mLastPeriodicSingleScanTimeStamp = currentTimeStamp;
startSingleScan(isFullBandScan, WIFI_WORK_SOURCE);
schedulePeriodicScanTimer(mPeriodicSingleScanInterval);
// Set up the next scan interval in an exponential backoff fashion.
mPeriodicSingleScanInterval *= 2;
if (mPeriodicSingleScanInterval > MAX_PERIODIC_SCAN_INTERVAL_MS) {
mPeriodicSingleScanInterval = MAX_PERIODIC_SCAN_INTERVAL_MS;
}
} else {
// Since we already skipped this scan, keep the same scan interval for next scan.
schedulePeriodicScanTimer(mPeriodicSingleScanInterval);
}
}
}
灭屏且有保存的网络
当设备处于灭屏状态,存在已保存的WiFi网络时,WiFi扫描行为会呈现出一种特定的模式。系统会根据之前的连接记录和网络状态,以高效且节能的方式管理WiFi连接。
- 「已连接网络的持续监控」:如果设备当前已连接到某个已保存的WiFi网络,系统会持续监控该网络的连接状态。只要连接稳定且信号良好,设备通常不会进行额外的WiFi扫描。
- 「未连接网络的PNO扫描」:如果设备未连接到任何已保存的WiFi网络,会执行PNO(Preferred Network Offload)扫描。扫描仅针对已保存的网络列表进行,而不是对整个可用网络进行扫描。有助于节省设备能耗,同时确保能够快速连接到已知的、可信的网络。
- 「扫描间隔优化」:为了平衡扫描的准确性和设备的能耗,PNO扫描的间隔会经过优化。通常情况下,最小扫描间隔可能设置为20秒,而最大间隔可能根据网络状况和设备策略进行调整,通常不会超过几分钟。确保了设备在需要时能够及时发现并连接到已保存的网络,同时不会在不需要时过度消耗电池电量。
- 「用户位置和网络变化的响应」:如果在灭屏状态下移动到了新的位置,或者网络状态发生了变化(例如,其他已保存的网络变得可用),系统可能会根据这些变化调整扫描策略。包括缩短扫描间隔或触发额外的扫描,以确保设备能够及时响应这些变化。
- 「系统通知和提醒」:当设备发现已保存的WiFi网络变得可用时,可能会通过系统通知或提醒来告知用户。用户可以选择手动连接到该网络,或者设置设备在下次亮屏时自动连接。
灭屏且有保存的网络,最小间隔min=20s,最大间隔max=20s*3=60s,不同Android版本可能存在差异。
无保存网络
当设备处于无保存网络的状态时,WiFi扫描行为会呈现出一种特定的模式。在这种情况下,设备没有预先保存的WiFi网络信息,需要通过扫描来寻找可用的网络。
- 「定期扫描」:由于没有保存的网络信息,设备会定期进行WiFi扫描,以搜索并发现可用的网络。扫描通常是在设备处于亮屏状态时进行的,扫描的频率可能会受到系统策略和设备设置的影响。
- 「扫描间隔」:在无保存网络的情况下,扫描间隔可能会相对较长,以减少设备的能耗。具体的扫描间隔因设备和系统版本的不同而有所差异,通常会设置为几分钟或更长的时间。
- 「用户交互触发」:除了定期扫描外,也可以通过一些交互操作来触发WiFi扫描。例如,可以在设置菜单中手动打开WiFi开关,或者通过下拉通知栏并点击WiFi图标来触发扫描。
- 「网络选择提示」:当设备发现可用的WiFi网络时,系统通常会显示一个通知或提示,告知有新的网络可用。可以点击通知来查看网络列表,并选择要连接的网络。
- 「安全性与信号强度考虑」:在选择要连接的网络时,通常会考虑网络的安全性和信号强度。系统会显示每个网络的安全性信息(如开放网络、WPA2-PSK等)以及信号强度指示,帮助用户做出更明智的连接决策。
//WifiStateMachine.java
class DisconnectedState extends State {
@Override
public void enter() {
Log.i(TAG, "disconnectedstate enter");
// We dont scan frequently if this is a temporary disconnect
// due to p2p
if (mTemporarilyDisconnectWifi) {
p2pSendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE);
return;
}
/** clear the roaming state, if we were roaming, we failed */
mIsAutoRoaming = false;
mWifiConnectivityManager.handleConnectionStateChanged(
WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
/**
* 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.
*/
if (mNoNetworksPeriodicScan != 0 && !mP2pConnected.get()
&& mWifiConfigManager.getSavedNetworks().size() == 0) {
sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
++mPeriodicScanToken, 0), mNoNetworksPeriodicScan);
}
mDisconnectedTimeStamp = mClock.getWallClockMillis();
mWifiStateTracker.updateState(WifiStateTracker.DISCONNECTED);
}
}
//其中扫描周期
mNoNetworksPeriodicScan = mContext.getResources().getInteger(R.integer.config_wifi_no_network_periodic_scan_interval);
frameworks/base/core/res/res/values/config.xmlmNoNetworksPeriodicScan在config.xml中注册,周期为5分钟
<!-- Integer indicating the framework no networks periodic scan interval in milliseconds. -->
<integer translatable="false" name="config_wifi_no_network_periodic_scan_interval">300000</integer>
为了优化能耗和用户体验,Android系统可能会采用一些节能策略来限制WiFi扫描的频率和持续时间。例如,在设备处于灭屏状态时,系统可能会减少或暂停WiFi扫描,以延长电池寿命。而在设备电量较低或处于节能模式下时,系统也可能会限制WiFi扫描的行为。