从点击 Settings Wifi界面中”refresh” 开始追代码流程 :
####packages Settings
case MENU_ID_SCAN:
MetricsLogger.action(getActivity(), MetricsLogger.ACTION_WIFI_FORCE_SCAN);
mWifiTracker.forceScan();
return true;
####frameworks settingslib WifiTracker
public void forceScan() {
if (mWifiManager.isWifiEnabled() && mScanner != null) {
mScanner.forceScan();
}
}
class Scanner extends Handler {
static final int MSG_SCAN = 0;
void forceScan() {
removeMessages(MSG_SCAN);
sendEmptyMessage(MSG_SCAN);
}
public void handleMessage(Message message) {
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(0, WIFI_RESCAN_INTERVAL_MS); //WIFI_RESCAN_INTERVAL_MS = 10 * 1000
}
}
开始10s一次的循环扫描 ,3次扫描失败则停止扫描。 ####WifiManager -> WifiService startScan(null, null)
public void startScan(ScanSettings settings, WorkSource workSource) {
enforceChangePermission();
......
mWifiStateMachine.startScan(Binder.getCallingUid(), scanRequestCounter++,
settings, workSource);
}
->WifiStateMachine
sendMessage(CMD_START_SCAN, callingUid, scanCounter, bundle);
handleScanRequest(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, message);
private void handleScanRequest(int type, Message message) {
ScanSettings settings = null;
WorkSource workSource = null;
......
// call wifi native to start the scan
if (startScanNative(type, freqs)) {
......
return;
}
// if reach here, scan request is rejected
......
}
->WifiNative
doBooleanCommand("SCAN"); //向wpa_supplicant下 "SCAN" command
到这里上层scan 结束, 下面看搜到 event 的处理
wpa_supplicant 发出 CTRL-EVENT-SCAN-RESULTS 给 WifiMonito , 在 dispatchEvent 中向 WifiStateMachine 发送 SCAN_RESULTS_EVENT ,处理的地方是 SupplicantStartedState
case WifiMonitor.SCAN_FAILED_EVENT:
maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered
noteScanEnd();
setScanResults(); //获取scanResults
if (mIsFullScanOngoing || mSendScanResultsBroadcast) {
/* Just updated results from full scan, let apps know about this */
boolean scanSucceeded = message.what == WifiMonitor.SCAN_RESULTS_EVENT;
sendScanResultsAvailableBroadcast(scanSucceeded); //通知其他app wifi scan result
}
mSendScanResultsBroadcast = false;
mIsScanOngoing = false;
mIsFullScanOngoing = false;
if (mBufferedScanMsg.size() > 0)
sendMessage(mBufferedScanMsg.remove());
break;
在 setScanResults 中先向 wpas 下 “BSS RANGE=0- MASK=0x21987” 获取搜索结果,获取到的结果如下,每个AP之间用”====”分割,末尾以“####”来表示结束
id=8730
bssid=38:83:45:0d:54:42
freq=2472
level=-75
tsf=0000207703501464
flags=[WPA2-PSK-CCMP+TKIP-preauth][ESS]
ssid=POWER-NB
====
id=8731
bssid=c8:60:00:93:f2:5a
freq=2467
level=-76
tsf=0000207703501484
flags=[WPA2-PSK-CCMP][ESS]
ssid=ASUS 2.4G
####
搜索结构先保存在 mScanResults 这个 List
而在 sendScanResultsAvailableBroadcast 中会发送 WifiManager.SCAN_RESULTS_AVAILABLE_ACTION 的 broadcast, Settings 中由 frameworks 中的 WifiTracker 中处理该事件
} else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action) ||
WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action) ||
WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)) {
mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
最后都是在 updateAccessPoints 中处理 , 主要是将搜索结果解析之后保存到 mAccessPoints ,并发 MSG_ACCESS_POINT_CHANGED 。
这个 event 的处理会调用到上层注册的 mListener.onConnectedChanged() , 这样回到 Settings 中的 WifiSettings 中重绘搜索列表。