Android設(shè)備WiFi掃描策略:在亮屏與滅屏狀態(tài)下,系統(tǒng)如何高效管理網(wǎng)絡(luò)連接
WiFi掃描場(chǎng)景
WiFi掃描場(chǎng)景根據(jù)設(shè)備的屏幕狀態(tài)、用戶(hù)當(dāng)前的活動(dòng)以及網(wǎng)絡(luò)環(huán)境的不同,而采用了不同的掃描策略。
1.「亮屏且在WiFi設(shè)置界面」:
當(dāng)用戶(hù)在亮屏狀態(tài)下進(jìn)入WiFi設(shè)置界面時(shí),設(shè)備會(huì)進(jìn)行固定掃描,掃描時(shí)間通常為10秒。這種掃描是為了快速獲取當(dāng)前可用的WiFi網(wǎng)絡(luò)列表,供用戶(hù)選擇連接。
2.「亮屏且不在WiFi設(shè)置界面」:
在這種情況下,Android設(shè)備會(huì)采用二進(jìn)制指數(shù)退避掃描策略。掃描間隔會(huì)根據(jù)一定的算法逐漸增長(zhǎng),最小間隔為20秒,最大間隔可能達(dá)到160秒。這種策略有助于平衡設(shè)備的能耗和WiFi掃描的效率。
3.「滅屏且有保存的網(wǎng)絡(luò)」:如果設(shè)備處于滅屏狀態(tài),但之前有保存過(guò)WiFi網(wǎng)絡(luò),那么設(shè)備會(huì)根據(jù)當(dāng)前的網(wǎng)絡(luò)連接狀態(tài)進(jìn)行掃描。如果已連接到某個(gè)網(wǎng)絡(luò),則不會(huì)進(jìn)行掃描;否則,設(shè)備會(huì)進(jìn)行PNO(Preferred Network Offload)掃描,即只掃描已保存的網(wǎng)絡(luò)。這種掃描的最小間隔為20秒,最大間隔為60秒。
4.無(wú)保存網(wǎng)絡(luò)」:
在沒(méi)有保存任何WiFi網(wǎng)絡(luò)的情況下,設(shè)備會(huì)進(jìn)行固定掃描,掃描間隔通常為5分鐘。這種掃描的目的是為了通知用戶(hù)周?chē)嬖诳捎玫拈_(kāi)放網(wǎng)絡(luò)。
還有一些特殊場(chǎng)景下的WiFi掃描,例如:
「位置變化」:當(dāng)用戶(hù)攜帶設(shè)備移動(dòng)到新的位置時(shí),設(shè)備可能會(huì)自動(dòng)觸發(fā)WiFi掃描,以尋找并連接到新的可用網(wǎng)絡(luò)。
「應(yīng)用請(qǐng)求」:某些應(yīng)用可能需要在后臺(tái)請(qǐng)求WiFi掃描,以獲取周?chē)木W(wǎng)絡(luò)信息或進(jìn)行其他相關(guān)操作。在這種情況下,Android系統(tǒng)會(huì)根據(jù)應(yīng)用的權(quán)限和策略來(lái)決定是否允許掃描。
亮屏且在WiFi設(shè)置界面
當(dāng)設(shè)備處于亮屏狀態(tài)且正在WiFi設(shè)置界面時(shí),WiFi掃描的行為會(huì)更為活躍和精確。這是為了提供一個(gè)實(shí)時(shí)、準(zhǔn)確的可用WiFi網(wǎng)絡(luò)列表,以便能夠方便地選擇并連接到合適的網(wǎng)絡(luò)。
- 「實(shí)時(shí)掃描」:當(dāng)打開(kāi)WiFi設(shè)置界面時(shí),系統(tǒng)會(huì)立即啟動(dòng)一次WiFi掃描。這次掃描是實(shí)時(shí)的,會(huì)立即搜索并列出當(dāng)前可用的WiFi網(wǎng)絡(luò)。
- 「持續(xù)刷新」:一旦掃描開(kāi)始,系統(tǒng)會(huì)持續(xù)刷新WiFi網(wǎng)絡(luò)列表,以確保列出的網(wǎng)絡(luò)是最新的。通過(guò)定期重新掃描或監(jiān)聽(tīng)網(wǎng)絡(luò)變化事件來(lái)實(shí)現(xiàn)的。
- 「網(wǎng)絡(luò)信號(hào)強(qiáng)度顯示」:在WiFi設(shè)置界面,除了列出網(wǎng)絡(luò)名稱(chēng)(SSID)外,系統(tǒng)還會(huì)顯示每個(gè)網(wǎng)絡(luò)的信號(hào)強(qiáng)度。這有助于判斷哪個(gè)網(wǎng)絡(luò)的信號(hào)更好,從而做出更明智的連接選擇。
- 「安全性標(biāo)識(shí)」:對(duì)于每個(gè)列出的WiFi網(wǎng)絡(luò),系統(tǒng)還會(huì)顯示其安全性信息(如開(kāi)放網(wǎng)絡(luò)、WPA2-PSK等)。這有助于了解網(wǎng)絡(luò)的安全性,并決定是否信任并連接到該網(wǎng)絡(luò)。
- 「用戶(hù)交互」:在WiFi設(shè)置界面,可以進(jìn)行多種操作,如點(diǎn)擊某個(gè)網(wǎng)絡(luò)進(jìn)行連接、輸入密碼、忘記網(wǎng)絡(luò)等。這些操作會(huì)觸發(fā)相應(yīng)的系統(tǒng)響應(yīng),如啟動(dòng)連接過(guò)程、驗(yàn)證密碼等。
亮屏且在WiFi設(shè)置界面時(shí)設(shè)備會(huì)進(jìn)行固定掃描,掃描時(shí)間通常為10秒。這種掃描是為了快速獲取當(dāng)前可用的WiFi網(wǎng)絡(luò)列表,供用戶(hù)選擇連接。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設(shè)置界面
當(dāng)設(shè)備的屏幕處于亮屏狀態(tài),但并不在WiFi設(shè)置界面時(shí),WiFi掃描的行為會(huì)有所不同。在這種情況下,系統(tǒng)會(huì)根據(jù)一系列策略和算法來(lái)管理WiFi掃描,以平衡設(shè)備的能耗、性能和用戶(hù)體驗(yàn)。
- 「減少掃描頻率」:與在WiFi設(shè)置界面時(shí)相比,當(dāng)不在該界面時(shí),系統(tǒng)通常會(huì)減少WiFi掃描的頻率。這是為了降低設(shè)備的能耗,并避免在不必要的情況下進(jìn)行過(guò)多的網(wǎng)絡(luò)搜索。
- 「二進(jìn)制指數(shù)退避掃描」:為了進(jìn)一步優(yōu)化掃描行為,Android系統(tǒng)可能會(huì)采用二進(jìn)制指數(shù)退避掃描策略。每次掃描之間的間隔會(huì)逐漸增加,基于一個(gè)退避算法。初始間隔可能較短,但隨著連續(xù)掃描次數(shù)的增加,間隔會(huì)逐漸延長(zhǎng)。這種策略有助于減少掃描的頻繁性,同時(shí)能夠保持對(duì)可用網(wǎng)絡(luò)的檢測(cè)能力。
- 「應(yīng)用層請(qǐng)求」:盡管系統(tǒng)減少了自動(dòng)掃描的頻率,但應(yīng)用程序仍然可以在后臺(tái)請(qǐng)求WiFi掃描。例如,某些應(yīng)用可能需要獲取周?chē)木W(wǎng)絡(luò)信息以執(zhí)行其功能。在這種情況下,系統(tǒng)會(huì)評(píng)估應(yīng)用的權(quán)限和請(qǐng)求,并根據(jù)需要執(zhí)行掃描。
- 「位置和網(wǎng)絡(luò)變化觸發(fā)」:如果設(shè)備的位置發(fā)生變化或檢測(cè)到網(wǎng)絡(luò)狀態(tài)發(fā)生變化(例如,從移動(dòng)數(shù)據(jù)切換到WiFi),系統(tǒng)可能會(huì)自動(dòng)觸發(fā)一次WiFi掃描。確保設(shè)備能夠及時(shí)發(fā)現(xiàn)并連接到新的可用網(wǎng)絡(luò)。
- 「用戶(hù)手動(dòng)觸發(fā)」:盡管系統(tǒng)減少了自動(dòng)掃描,仍然可以手動(dòng)觸發(fā)WiFi掃描。例如,可以通過(guò)下拉通知欄并點(diǎn)擊“WiFi”圖標(biāo)來(lái)重新掃描可用網(wǎng)絡(luò)。
亮屏且不在WiFi設(shè)置界面時(shí)掃描間隔會(huì)根據(jù)一定的算法逐漸增長(zhǎng),最小間隔為20秒,最大間隔可能達(dá)到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);
}
}
}
滅屏且有保存的網(wǎng)絡(luò)
當(dāng)設(shè)備處于滅屏狀態(tài),存在已保存的WiFi網(wǎng)絡(luò)時(shí),WiFi掃描行為會(huì)呈現(xiàn)出一種特定的模式。系統(tǒng)會(huì)根據(jù)之前的連接記錄和網(wǎng)絡(luò)狀態(tài),以高效且節(jié)能的方式管理WiFi連接。
- 「已連接網(wǎng)絡(luò)的持續(xù)監(jiān)控」:如果設(shè)備當(dāng)前已連接到某個(gè)已保存的WiFi網(wǎng)絡(luò),系統(tǒng)會(huì)持續(xù)監(jiān)控該網(wǎng)絡(luò)的連接狀態(tài)。只要連接穩(wěn)定且信號(hào)良好,設(shè)備通常不會(huì)進(jìn)行額外的WiFi掃描。
- 「未連接網(wǎng)絡(luò)的PNO掃描」:如果設(shè)備未連接到任何已保存的WiFi網(wǎng)絡(luò),會(huì)執(zhí)行PNO(Preferred Network Offload)掃描。掃描僅針對(duì)已保存的網(wǎng)絡(luò)列表進(jìn)行,而不是對(duì)整個(gè)可用網(wǎng)絡(luò)進(jìn)行掃描。有助于節(jié)省設(shè)備能耗,同時(shí)確保能夠快速連接到已知的、可信的網(wǎng)絡(luò)。
- 「掃描間隔優(yōu)化」:為了平衡掃描的準(zhǔn)確性和設(shè)備的能耗,PNO掃描的間隔會(huì)經(jīng)過(guò)優(yōu)化。通常情況下,最小掃描間隔可能設(shè)置為20秒,而最大間隔可能根據(jù)網(wǎng)絡(luò)狀況和設(shè)備策略進(jìn)行調(diào)整,通常不會(huì)超過(guò)幾分鐘。確保了設(shè)備在需要時(shí)能夠及時(shí)發(fā)現(xiàn)并連接到已保存的網(wǎng)絡(luò),同時(shí)不會(huì)在不需要時(shí)過(guò)度消耗電池電量。
- 「用戶(hù)位置和網(wǎng)絡(luò)變化的響應(yīng)」:如果在滅屏狀態(tài)下移動(dòng)到了新的位置,或者網(wǎng)絡(luò)狀態(tài)發(fā)生了變化(例如,其他已保存的網(wǎng)絡(luò)變得可用),系統(tǒng)可能會(huì)根據(jù)這些變化調(diào)整掃描策略。包括縮短掃描間隔或觸發(fā)額外的掃描,以確保設(shè)備能夠及時(shí)響應(yīng)這些變化。
- 「系統(tǒng)通知和提醒」:當(dāng)設(shè)備發(fā)現(xiàn)已保存的WiFi網(wǎng)絡(luò)變得可用時(shí),可能會(huì)通過(guò)系統(tǒng)通知或提醒來(lái)告知用戶(hù)。用戶(hù)可以選擇手動(dòng)連接到該網(wǎng)絡(luò),或者設(shè)置設(shè)備在下次亮屏?xí)r自動(dòng)連接。
滅屏且有保存的網(wǎng)絡(luò),最小間隔min=20s,最大間隔max=20s*3=60s,不同Android版本可能存在差異。
無(wú)保存網(wǎng)絡(luò)
當(dāng)設(shè)備處于無(wú)保存網(wǎng)絡(luò)的狀態(tài)時(shí),WiFi掃描行為會(huì)呈現(xiàn)出一種特定的模式。在這種情況下,設(shè)備沒(méi)有預(yù)先保存的WiFi網(wǎng)絡(luò)信息,需要通過(guò)掃描來(lái)尋找可用的網(wǎng)絡(luò)。
- 「定期掃描」:由于沒(méi)有保存的網(wǎng)絡(luò)信息,設(shè)備會(huì)定期進(jìn)行WiFi掃描,以搜索并發(fā)現(xiàn)可用的網(wǎng)絡(luò)。掃描通常是在設(shè)備處于亮屏狀態(tài)時(shí)進(jìn)行的,掃描的頻率可能會(huì)受到系統(tǒng)策略和設(shè)備設(shè)置的影響。
- 「掃描間隔」:在無(wú)保存網(wǎng)絡(luò)的情況下,掃描間隔可能會(huì)相對(duì)較長(zhǎng),以減少設(shè)備的能耗。具體的掃描間隔因設(shè)備和系統(tǒng)版本的不同而有所差異,通常會(huì)設(shè)置為幾分鐘或更長(zhǎng)的時(shí)間。
- 「用戶(hù)交互觸發(fā)」:除了定期掃描外,也可以通過(guò)一些交互操作來(lái)觸發(fā)WiFi掃描。例如,可以在設(shè)置菜單中手動(dòng)打開(kāi)WiFi開(kāi)關(guān),或者通過(guò)下拉通知欄并點(diǎn)擊WiFi圖標(biāo)來(lái)觸發(fā)掃描。
- 「網(wǎng)絡(luò)選擇提示」:當(dāng)設(shè)備發(fā)現(xiàn)可用的WiFi網(wǎng)絡(luò)時(shí),系統(tǒng)通常會(huì)顯示一個(gè)通知或提示,告知有新的網(wǎng)絡(luò)可用??梢渣c(diǎn)擊通知來(lái)查看網(wǎng)絡(luò)列表,并選擇要連接的網(wǎng)絡(luò)。
- 「安全性與信號(hào)強(qiáng)度考慮」:在選擇要連接的網(wǎng)絡(luò)時(shí),通常會(huì)考慮網(wǎng)絡(luò)的安全性和信號(hào)強(qiáng)度。系統(tǒng)會(huì)顯示每個(gè)網(wǎng)絡(luò)的安全性信息(如開(kāi)放網(wǎng)絡(luò)、WPA2-PSK等)以及信號(hào)強(qiáng)度指示,幫助用戶(hù)做出更明智的連接決策。
//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中注冊(cè),周期為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>
為了優(yōu)化能耗和用戶(hù)體驗(yàn),Android系統(tǒng)可能會(huì)采用一些節(jié)能策略來(lái)限制WiFi掃描的頻率和持續(xù)時(shí)間。例如,在設(shè)備處于滅屏狀態(tài)時(shí),系統(tǒng)可能會(huì)減少或暫停WiFi掃描,以延長(zhǎng)電池壽命。而在設(shè)備電量較低或處于節(jié)能模式下時(shí),系統(tǒng)也可能會(huì)限制WiFi掃描的行為。