Android設備WiFi掃描策略:在亮屏與滅屏狀態下,系統如何高效管理網絡連接
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掃描的行為。