版权声明:本文为博主原创文章,博客地址:https://blog.csdn.net/h784707460/article/details/79702275,未经博主允许不得转载。
一、 Android O wifi扫描机制
Android O的扫面场景可以归结为以下四种:
详见 Android wifi扫描机制(Android O)
1、 亮屏情况下,在Wifi settings界面,固定扫描,时间间隔为10s。
2、 亮屏情况下,非Wifi settings界面,二进制指数退避扫描,退避:interval*(2^n), 最小间隔min=20s, 最大间隔max=160s.3、 灭屏情况下,有保存网络时,若已连接,不扫描,否则,PNO扫描,即只扫描已保存的网络。最小间隔min=20s,最大间隔max=20s*3.
4、 无保存网络情况下,固定扫描,间隔为5分钟,用于通知用户周围存在可用开放网络。
其中场景1/2/4中的扫描是全信道扫描,扫描控制逻辑在Android framework,涉及模块依次是WifiTracker、WifiConnectivityManager、WifiStateMachine。场景3中的扫描是PNO扫描,即只扫描已保存的网络,PNO扫描的控制逻辑涉及较广,从上到下(Qcom平台):WifiConnectivityManager、WifiScanner、WifiScanningServiceImpl、WifiNative、wificond、wifi driver、firmware。
二、 Android O wifi PNO扫描流程
灭屏时,WifiConnectivityManager中handleScreenStateChanged函数会判断是否触发PNO扫描。并且进行PNO扫描列表设置、PNO扫描间隔(20s)设置等PNO扫描的参数设置。
public void handleScreenStateChanged
startConnectivityScan(SCAN_ON_SCHEDULE); //开关屏幕时会触发对应的扫描
private void startConnectivityScan(boolean scanImmediately)
if (mScreenOn) {
startPeriodicScan(scanImmediately);
} else {
if (mWifiState == WIFI_STATE_DISCONNECTED && !mPnoScanStarted) {
startDisconnectedPnoScan(); //灭屏无连接时启动PNO扫描,不重复启动
}
private void startDisconnectedPnoScan()
if (listSize == 0) {
// No saved network
return; // 无保存网络时,不PNO扫描
}
//获取已保存网络列表。
//发送到firmware的PNO网络列表是受限的,如果已保存网络较多,该列表会被截断。选择网络的策略是根据连接频率排序及最后一次扫描到的网络中优先选择.
List<PnoSettings.PnoNetwork> pnoNetworkList = mConfigManager.retrievePnoNetworkList();
//设置PNO扫描间隔,20s
scanSettings.periodInMs = DISCONNECTED_PNO_SCAN_INTERVAL_MS;
//启动PNO扫描
mScanner.startDisconnectedPnoScan(scanSettings, pnoSettings, mPnoScanListener);
mPnoScanStarted = true;
WifiScanner启动PNO扫描流程
2>. WifiScanner.java
public void startDisconnectedPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings, PnoScanListener listener)
startPnoScan(scanSettings, pnoSettings, key);
private void startPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings, int key)
Bundle pnoParams = new Bundle();
scanSettings.isPnoScan = true;
pnoParams.putParcelable(PNO_PARAMS_SCAN_SETTINGS_KEY, scanSettings);
pnoParams.putParcelable(PNO_PARAMS_PNO_SETTINGS_KEY, pnoSettings);
mAsyncChannel.sendMessage(CMD_START_PNO_SCAN, 0, key, pnoParams);
WifiScanningServiceImpl中状态机中实现处理相关消息的逻辑
3>. WifiScanningServiceImpl.java
WifiPnoScanStateMachine //5个状态
-Default State
-Started State
-Hw Pno Scan state
-Single Scan state
-Sw Pno Scan state
StartedState
case WifiScanner.CMD_START_PNO_SCAN:
if (mScannerImpl.isHwPnoSupported(pnoSettings.isConnected)) {
transitionTo(mHwPnoScanState);//@1 mHwPnoScanState=true
} else {
transitionTo(mSwPnoScanState);
}
@1: mHwPnoScanSupported = mContext.getResources().getBoolean(
R.bool.config_wifi_background_scan_support); //ture
HwPnoScanState
case WifiScanner.CMD_START_PNO_SCAN:
addHwPnoScanRequest(ci, msg.arg2, scanSettings, pnoSettings)
addHwPnoScanRequest
WifiNative.PnoSettings nativePnoSettings = convertSettingsToPnoNative(scanSettings, pnoSettings); //传递PNO scan settings参数
addPnoScanRequest(ci, handler, scanSettings, pnoSettings);
if (mScannerImpl.shouldScheduleBackgroundScanForHwPno()) { //@2 false
addBackgroundScanRequest(scanSettings);
}
@2: public boolean shouldScheduleBackgroundScanForHwPno() {
return false;
} //WificondScannerImpl.java
addPnoScanRequest(ClientInfo ci, int handler, ScanSettings scanSettings,PnoSettings pnoSettings)
mActivePnoScans.addRequest(ci, handler, WifiStateMachine.WIFI_WORK_SOURCE, Pair.create(pnoSettings, scanSettings));
addInternalClient(ci);
4>. WificondScannerImpl.java
handleMessage
case WifiMonitor.SCAN_RESULTS_EVENT:
processPendingScans();
Wait for the active scan result to come back to reschedule other scans, unless if HW pno scan is running. Hw PNO scans are paused it if there are other pending scans,
// 等待主动扫描的结果来安排其他扫描,除非PNO扫描正在运行。如果有其他扫描HW PNO扫描会被暂停.
private void processPendingScans()
// If the PNO network list has changed from the previous request, ensure that
// we bypass the debounce logic and restart PNO scan.
if (isDifferentPnoScanSettings(newScanSettings)) {
status = restartHwPnoScan(mPnoSettings);
} else {
status = startHwPnoScan(mPnoSettings);
}
private boolean restartHwPnoScan(WifiNative.PnoSettings pnoSettings) or
private boolean startHwPnoScan(WifiNative.PnoSettings pnoSettings)
return mHwPnoDebouncer.startPnoScan(pnoSettings, mHwPnoDebouncerListener);
public boolean startPnoScan(WifiNative.PnoSettings pnoSettings, Listener listener)
setPnoState(true)
private boolean setPnoState(boolean enable)
isSuccess = startPnoScanInternal();
private boolean startPnoScanInternal()
mWifiNative.startPnoScan(mPnoSettings)
5>. WifiNative.java
public boolean startPnoScan(PnoSettings pnoSettings)
return mWificondControl.startPnoScan(pnoSettings);
6>. WificondControl.java
public boolean startPnoScan(WifiNative.PnoSettings pnoSettings)
boolean success = mWificondScanner.startPnoScan(settings);
7>. /wificond/scanning/scanner_impl.cpp
ScannerImpl::startPnoScan
if (offload_scan_supported_ && StartPnoScanOffload(pno_settings)) {
// scanning over offload succeeded
*out_success = true;
} else {
*out_success = StartPnoScanDefault(pno_settings);
}
ScannerImpl::StartPnoScanDefault
scan_utils_->StartScheduledScan(interface_index_,
GenerateIntervalSetting(pno_settings),
pno_settings.min_5g_rssi_,
request_random_mac,
scan_ssids,
match_ssids,
freqs,
&error_code)
SchedScanIntervalSetting ScannerImpl::GenerateIntervalSetting
// {{20s, 3}, 3}, min=20s, max=20s*3
return SchedScanIntervalSetting{
{{fast_scan_interval, PnoSettings::kFastScanIterations}},
fast_scan_interval * PnoSettings::kSlowScanIntervalMultiplier};
8>. scan_utils.cpp
bool ScanUtils::StartScheduledScan
将PNO Scan参数传入kernel driver处理。
抓空口log发现,PNO扫描时间间隔为:20s、20s、60s、60s、....、60s