一、 Android O wifi扫描机制
Android O的扫面场景可以归结为以下四种:
1、 亮屏情况下,在Wifi settings界面,固定扫描,时间间隔为10s。
2、 亮屏情况下,非Wifi settings界面,二进制指数退避扫描,退避:interval*(2^n), 最小间隔min=20s, 最大间隔max=160s. 3、 灭屏情况下,有保存网络时,若已连接,不扫描,否则,PNO扫描,即只扫描已保存的网络。最小间隔min=20s,最大间隔max=20s*3=60s 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扫描的参数设置。
1>. WifiConnectivityManager.java public void handleScreenStateChanged startConnectivityScan(SCAN_ON_SCHEDULE); //开关屏幕时会触发对应的扫描 private void startConnectivityScan(boolean scanImmediately) if (mScreenOn) { startPeriodicScan(scanImmediately); } else { if (mWifiState == WIFI_STATE_DISCONNECTED //灭屏无连接时启动PNO扫描,不重复启动 } private void startDisconnectedPnoScan() if (listSize == 0) { // No saved network return; // 无保存网络时,不PNO扫描 } //获取已保存网络列表。 //发送到firmware的PNO网络列表是受限的,如果已保存网络较多,该列表会被截断。选择网络的策略是根据连接频率排序及最后一次扫描到的网络中优先选择. List
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_ } 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, 8>. scan_utils.cpp bool ScanUtils::StartScheduledScan
将PNO Scan参数传入kernel driver处理。
9>. Qcom WCN3990中, wifi driver将参数传入firmware,由firmware根据min=20s, max=20s*3的时间间隔控制扫描。 抓空口log发现,PNO扫描时间间隔为:20s、20s、60s、60s、....、60s
【文章原创作者:高防cdn http://www.558idc.com/gfcdn.html提供,感恩】