接(一百五十五)Android P wifi 扫描失败结果上报流程梳理-扫描上报梳理 扫描失败上报梳理发现梳理的差了很多,特补充
1.WificondScannerImpl
@Override
public boolean startSingleScan(WifiNative.ScanSettings settings,
WifiNative.ScanEventHandler eventHandler) {
if (eventHandler == null || settings == null) {
Log.w(TAG, "Invalid arguments for startSingleScan: settings=" + settings
+ ",eventHandler=" + eventHandler);
return false;
}
synchronized (mSettingsLock) {
if (mLastScanSettings != null) {
Log.w(TAG, "A single scan is already running");
return false;
}
ChannelCollection allFreqs = mChannelHelper.createChannelCollection();
boolean reportFullResults = false;
for (int i = 0; i < settings.num_buckets; ++i) {
WifiNative.BucketSettings bucketSettings = settings.buckets[i];
if ((bucketSettings.report_events
& WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) {
reportFullResults = true;
}
allFreqs.addChannels(bucketSettings);
}
Set hiddenNetworkSSIDSet = new HashSet<>();
if (settings.hiddenNetworks != null) {
int numHiddenNetworks =
Math.min(settings.hiddenNetworks.length, MAX_HIDDEN_NETWORK_IDS_PER_SCAN);
for (int i = 0; i < numHiddenNetworks; i++) {
hiddenNetworkSSIDSet.add(settings.hiddenNetworks[i].ssid);
}
}
mLastScanSettings = new LastScanSettings(
mClock.getElapsedSinceBootMillis(),
reportFullResults, allFreqs, eventHandler);
boolean success = false;
Set freqs;
if (!allFreqs.isEmpty()) {
freqs = allFreqs.getScanFreqs();
success = mWifiNative.scan(
mIfaceName, settings.scanType, freqs, hiddenNetworkSSIDSet);
if (!success) {
Log.e(TAG, "Failed to start scan, freqs=" + freqs);
}
} else {
// There is a scan request but no available channels could be scanned for.
// We regard it as a scan failure in this case.
Log.e(TAG, "Failed to start scan because there is no available channel to scan");
}
if (success) {
if (DBG) {
Log.d(TAG, "Starting wifi scan for freqs=" + freqs);
}
mScanTimeoutListener = new AlarmManager.OnAlarmListener() {
@Override public void onAlarm() {
handleScanTimeout();
}
};
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
mClock.getElapsedSinceBootMillis() + SCAN_TIMEOUT_MS,
TIMEOUT_ALARM_TAG, mScanTimeoutListener, mEventHandler);
} else {
// indicate scan failure async
mEventHandler.post(new Runnable() {
@Override public void run() {
reportScanFailure();
}
});
}
return true;
}
}
1.1 命令下发成功后的失败
下发扫描命令成功后会设立一个15s的倒计时,若15s没有失败或者成功上报就会上报一个失败,最终触发广播通知
/**
* Duration to wait before timing out a scan.
*
* The expected behavior is that the hardware will return a failed scan if it does not
* complete, but timeout just in case it does not.
*/
private static final long SCAN_TIMEOUT_MS = 15000;
private void handleScanTimeout() {
synchronized (mSettingsLock) {
Log.e(TAG, "Timed out waiting for scan result from wificond");
reportScanFailure();
mScanTimeoutListener = null;
}
}
@Override
public boolean handleMessage(Message msg) {
switch(msg.what) {
case WifiMonitor.SCAN_FAILED_EVENT:
Log.w(TAG, "Scan failed");
cancelScanTimeout();
reportScanFailure();
break;
case WifiMonitor.PNO_SCAN_RESULTS_EVENT:
pollLatestScanDataForPno();
break;
case WifiMonitor.SCAN_RESULTS_EVENT:
cancelScanTimeout();
pollLatestScanData();
break;
default:
// ignore unknown event
}
return true;
}
另外扫描结果获取失败也会回调上来告诉上层获取扫描结果失败
与扫描结果成功对应的有个失败的回调
scanner_impl.java
void ScannerImpl::OnScanResultsReady(uint32_t interface_index, bool aborted,
vector>& ssids,
vector& frequencies) {
if (!scan_started_) {
LOG(INFO) << "Received external scan result notification from kernel.";
}
scan_started_ = false;
if (scan_event_handler_ != nullptr) {
// TODO: Pass other parameters back once we find framework needs them.
if (aborted) {
LOG(WARNING) << "Scan aborted";
scan_event_handler_->OnScanFailed();
} else {
scan_event_handler_->OnScanResultReady();
}
} else {
LOG(WARNING) << "No scan event handler found.";
}
}
http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.java#97
83 private class ScanEventHandler extends IScanEvent.Stub {
84 private String mIfaceName;
85
86 ScanEventHandler(@NonNull String ifaceName) {
87 mIfaceName = ifaceName;
88 }
89
90 @Override
91 public void OnScanResultReady() {
92 Log.d(TAG, "Scan result ready event");
93 mWifiMonitor.broadcastScanResultEvent(mIfaceName);
94 }
95
96 @Override
97 public void OnScanFailed() {
98 Log.d(TAG, "Scan failed event");
99 mWifiMonitor.broadcastScanFailedEvent(mIfaceName);
100 }
101 }
http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java#268
265 @Override
266 public boolean handleMessage(Message msg) {
267 switch(msg.what) {
268 case WifiMonitor.SCAN_FAILED_EVENT:
269 Log.w(TAG, "Scan failed");
270 cancelScanTimeout();
271 reportScanFailure();
272 break;
1.2 命令下发的失败
可以看到这个扫描命令流程下发一直会有个执行成功or失败的返回值,这会告诉上层执行命令的成功与否。
2.总结
扫描失败分
扫描命令下发失败
扫描过程中失败
扫描结果获取超时
扫描命令下发成功其实就是打个log,后续失败一直会上报给上层,上层会以广播的形式告知,命令下发后kernel去扫描,扫描到结果后会告诉上层来取,上层这时会再下发命令将扫描结果取上来,而不是之前想的kernel扫描到结果后就直接将结果报上来上层直接就用了,上层并没有用回调上来的结果,而是自己知道结果好了又向kernel要了下结果。
这段逻辑在
http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java#276
http://androidxref.com/9.0.0_r3/xref/system/connectivity/wificond/scanning/scan_utils.cpp#77