本文主要是介绍(一百七十八)WiFi扫描结果framework和app共享么?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1.流程回顾
WifiScanningServiceImpl
case WifiScanner.CMD_START_SINGLE_SCAN:mWifiMetrics.incrementOneshotScanCount();int handler = msg.arg2;Bundle scanParams = (Bundle) msg.obj;if (scanParams == null) {logCallback("singleScanInvalidRequest", ci, handler, "null params");replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "params null");return HANDLED;}scanParams.setDefusable(true);ScanSettings scanSettings =scanParams.getParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY);WorkSource workSource =scanParams.getParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY);if (validateScanRequest(ci, handler, scanSettings)) {logScanRequest("addSingleScanRequest", ci, handler, workSource,scanSettings, null);replySucceeded(msg);// If there is an active scan that will fulfill the scan request then// mark this request as an active scan, otherwise mark it pending.// If were not currently scanning then try to start a scan. Otherwise// this scan will be scheduled when transitioning back to IdleState// after finishing the current scan.if (getCurrentState() == mScanningState) {if (activeScanSatisfies(scanSettings)) {mActiveScans.addRequest(ci, handler, workSource, scanSettings);} else {mPendingScans.addRequest(ci, handler, workSource, scanSettings);}} else {mPendingScans.addRequest(ci, handler, workSource, scanSettings);tryToStartNewScan();}} else {logCallback("singleScanInvalidRequest", ci, handler, "bad request");replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "bad request");mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION, 1);}return HANDLED;
1.1 扫描命令下发
首先scan有个scanSettings的设定,即扫描不是都是一样的,有细致差别,具体是在scanSettings里携带的
如果scan设定当前的囊括新来的,那么就认为是一个类别的扫描,可以一起等刚刚下发的扫描命令返回上来的扫描结果,否则进入等待队列等下一次扫描
boolean activeScanSatisfies(ScanSettings settings) {if (mActiveScanSettings == null) {return false;}if (!activeScanTypeSatisfies(getNativeScanType(settings.type))) {return false;}// there is always one bucket for a single scanWifiNative.BucketSettings activeBucket = mActiveScanSettings.buckets[0];// validate that all requested channels are being scannedChannelCollection activeChannels = mChannelHelper.createChannelCollection();activeChannels.addChannels(activeBucket);if (!activeChannels.containsSettings(settings)) {return false;}// if the request is for a full scan, but there is no ongoing full scanif ((settings.reportEvents & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0&& (activeBucket.report_events & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT)== 0) {return false;}if (!ArrayUtils.isEmpty(settings.hiddenNetworks)) {if (ArrayUtils.isEmpty(mActiveScanSettings.hiddenNetworks)) {return false;}List<WifiNative.HiddenNetwork> activeHiddenNetworks = new ArrayList<>();for (WifiNative.HiddenNetwork hiddenNetwork : mActiveScanSettings.hiddenNetworks) {activeHiddenNetworks.add(hiddenNetwork);}for (ScanSettings.HiddenNetwork hiddenNetwork : settings.hiddenNetworks) {WifiNative.HiddenNetwork nativeHiddenNetwork = new WifiNative.HiddenNetwork();nativeHiddenNetwork.ssid = hiddenNetwork.ssid;if (!activeHiddenNetworks.contains(nativeHiddenNetwork)) {return false;}}}return true;}
会判断扫描的
- type(WifiNative.SCAN_TYPE_LOW_LATENCY WifiNative.SCAN_TYPE_LOW_POWER WifiNative.SCAN_TYPE_HIGH_ACCURACY)
- channel(settings用的是WIFI_BAND_BOTH_WITH_DFS即2.4+5+dfs)
- full scan
- hiddenNetworks
是否包含这次请求的扫描,这样不是返回上来的扫描结果会比要求的多么?没必要担心,后续有过滤
1.2 扫描结果过滤
case CMD_SCAN_RESULTS_AVAILABLE:mWifiMetrics.incrementScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS,mActiveScans.size());reportScanResults(mScannerImpl.getLatestSingleScanResults());mActiveScans.clear();transitionTo(mIdleState);return HANDLED;void reportScanResults(ScanData results) {if (results != null && results.getResults() != null) {if (results.getResults().length > 0) {mWifiMetrics.incrementNonEmptyScanResultCount();} else {mWifiMetrics.incrementEmptyScanResultCount();}}ScanData[] allResults = new ScanData[] {results};for (RequestInfo<ScanSettings> entry : mActiveScans) {ScanData[] resultsToDeliver = ScanScheduleUtil.filterResultsForSettings(mChannelHelper, allResults, entry.settings, -1);WifiScanner.ParcelableScanData parcelableResultsToDeliver =new WifiScanner.ParcelableScanData(resultsToDeliver);logCallback("singleScanResults", entry.clientInfo, entry.handlerId,describeForLog(resultsToDeliver));entry.reportEvent(WifiScanner.CMD_SCAN_RESULT, 0, parcelableResultsToDeliver);// make sure the handler is removedentry.reportEvent(WifiScanner.CMD_SINGLE_SCAN_COMPLETED, 0, null);}WifiScanner.ParcelableScanData parcelableAllResults =new WifiScanner.ParcelableScanData(allResults);for (RequestInfo<Void> entry : mSingleScanListeners) {logCallback("singleScanResults", entry.clientInfo, entry.handlerId,describeForLog(allResults));entry.reportEvent(WifiScanner.CMD_SCAN_RESULT, 0, parcelableAllResults);}if (results.isAllChannelsScanned()) {mCachedScanResults.clear();mCachedScanResults.addAll(Arrays.asList(results.getResults()));}}List<ScanResult> getCachedScanResultsAsList() {return mCachedScanResults;}}
这边的filterResultsForSettings会将扫描结果按扫描settings过滤一遍再返回回来,这样既考虑了扫描效率,又考虑了扫描Setting。
/*** Returns a filtered version of the scan results from the chip that represents only the data* requested in the settings. Will return null if the result should not be reported.** If a ScanData indicates that the bucket the settings were placed in was scanned then it* will always be included (filtered to only include requested channels). If it indicates that* the bucket was definitely not scanned then the scan data will not be reported.* If it is not possible to determine if the settings bucket was scanned or not then a* ScanData will be included if the scan was empty or there was at least one scan result that* matches a requested channel (again the results will be filtered to only include requested* channels.*/public static ScanData[] filterResultsForSettings(ChannelHelper channelHelper,ScanData[] scanDatas, ScanSettings settings, int scheduledBucket) {List<ScanData> filteredScanDatas = new ArrayList<>(scanDatas.length);List<ScanResult> filteredResults = new ArrayList<>();for (ScanData scanData : scanDatas) {// only report ScanData if the settings bucket could have been scannedif (isBucketMaybeScanned(scheduledBucket, scanData.getBucketsScanned())) {filteredResults.clear();for (ScanResult scanResult : scanData.getResults()) {if (channelHelper.settingsContainChannel(settings, scanResult.frequency)) {filteredResults.add(scanResult);}if (settings.numBssidsPerScan > 0&& filteredResults.size() >= settings.numBssidsPerScan) {break;}}// will include scan results if the scan was empty, there was at least one// one result that matched the scan request or we are sure that all the requested// channels were scanned.if (filteredResults.size() == scanData.getResults().length) {filteredScanDatas.add(scanData);} else if (filteredResults.size() > 0 || isBucketDefinitlyScanned(scheduledBucket,scanData.getBucketsScanned())) {filteredScanDatas.add(new ScanData(scanData.getId(),scanData.getFlags(),filteredResults.toArray(new ScanResult[filteredResults.size()])));}}}if (filteredScanDatas.size() == 0) {return null;} else {return filteredScanDatas.toArray(new ScanData[filteredScanDatas.size()]);}}
2.总结
WiFi扫描结果framework和app共享这个要看是否这两者的扫描settings处于包含关系,比如framework的扫描settings包含app的,那么它们可以共一次扫描的扫描结果,但是app拿到的扫描结果后续会按照scansettings过滤一下。
这样既考虑效率又考虑特殊需求的处理很符合逻辑了。
举例Settings的扫描是TYPE_HIGH_ACCURACY + WIFI_BAND_BOTH_WITH_DFS,而framework比如WifiConnectivityManager的扫描TYPE_HIGH_ACCURACY,但WIFI_BAND_BOTH_WITH_DFS不能保证。
另外扫描结果依赖注册的listener回调,即即使scan Settings一样,settings还没下发扫描,framework的扫描结果settings也是拿不到的,上层应用是从ScanRequestProxy下发扫描命令和获取扫描结果的,而WifiConnectivityManager是自己下发到WiFiscanner并且自己注册监听器的。
这篇关于(一百七十八)WiFi扫描结果framework和app共享么?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!