源码链接
从WiFi成功开启以后开始梳理:
1、ClientModeManager
private class StartedState extends State {
if (isUp) {
Log.d(TAG, "Wifi is ready to use for client mode");
sendScanAvailableBroadcast(true);
mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE,
mClientInterfaceName);
updateWifiState(WifiManager.WIFI_STATE_ENABLED,
WifiManager.WIFI_STATE_ENABLING);
.............
}
2、WifiTracker–>WifiManager
WifiTracker 广播监听到WifiManager.WIFI_STATE_CHANGED_ACTION ,执行updateWifiState,确认WIFi开启以后,执行Scanner的resume函数。开启wifiManager.StartScan
final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
updateWifiState(
intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN));
private void updateWifiState(int state) {
if (state == WifiManager.WIFI_STATE_ENABLED) {
if (mScanner != null) {
// We only need to resume if mScanner isn't null because
// that means we want to be scanning.
mScanner.resume();
}
resume函数会发送MSG_SCAN消息,MSG_SCAN消息的处理结果就是调用wifiManager.StartScan。
class Scanner extends Handler {
static final int MSG_SCAN = 0;
private int mRetry = 0;
void resume() {
if (!hasMessages(MSG_SCAN)) {
sendEmptyMessage(MSG_SCAN);
}
}
public void handleMessage(Message message) {
if (message.what != MSG_SCAN) return;
if (mWifiManager.startScan()) {
mRetry = 0;
3、WifiManager–>WifiServiceImpl
@RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
public boolean startScan(WorkSource workSource) {
try {
String packageName = mContext.getOpPackageName();
return mService.startScan(packageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
4、WifiServiceImpl–>ScanRequestProxy
public boolean startScan(String packageName) {
try {
mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, callingUid);
Mutable<Boolean> scanSuccess = new Mutable<>();
boolean runWithScissorsSuccess = mWifiInjector.getWifiStateMachineHandler()
.runWithScissors(() -> {
scanSuccess.value = mScanRequestProxy.startScan(callingUid, packageName);
}, RUN_WITH_SCISSORS_TIMEOUT_MILLIS);
return true;
}
5、ScanRequestProxy–>WifiScanner
先获取扫描的设置,然后再开始扫描。
public boolean startScan(int callingUid, String packageName) {
// Create the scan settings.
WifiScanner.ScanSettings settings = new WifiScanner.ScanSettings();
// Scan requests from apps with network settings will be of high accuracy type.
if (fromSettingsOrSetupWizard) {
settings.type = WifiScanner.TYPE_HIGH_ACCURACY;
}
// always do full scans
settings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;
settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
| WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
if (mScanningForHiddenNetworksEnabled) {
// retrieve the list of hidden network SSIDs to scan for, if enabled.
List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList =
mWifiConfigManager.retrieveHiddenNetworkList();
settings.hiddenNetworks = hiddenNetworkList.toArray(
new WifiScanner.ScanSettings.HiddenNetwork[hiddenNetworkList.size()]);
}
mWifiScanner.startScan(settings, new ScanRequestProxyScanListener(), workSource);
mIsScanProcessingComplete = false;
return true;
}
6、WifiScanner.–>WifiScanningServiceImpl
发送scan请求CMD_START_SINGLE_SCAN。
public void startScan(ScanSettings settings, ScanListener listener, WorkSource workSource) {
Preconditions.checkNotNull(listener, "listener cannot be null");
int key = addListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
Bundle scanParams = new Bundle();
scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
mAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams);
}
7、WifiScanningServiceImpl–>WifiScannerIm0l
先进行有效Scan检查
当前正在Scanning,如为有效的(活)scaning,标志为ActiveScans,否则标志为PendingScans
当前非Scanning,标志为PendingScans,开启一次新的Scan – tryToStartNewScan()
非有效Scan,上报错误Failed
class DriverStartedState extends State {
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_DRIVER_LOADED:
// Ignore if we're already in driver loaded state.
return HANDLED;
case WifiScanner.CMD_START_SINGLE_SCAN:
..............
} else {
mPendingScans.addRequest(ci, handler, workSource, scanSettings);
tryToStartNewScan();
}
}
}
void tryToStartNewScan() {
.............
if (mScannerImpl.startSingleScan(settings, this)) {
mPendingScans.clear();
transitionTo(mScanningState);
} else {
mWifiMetrics.incrementScanReturnEntry(
WifiMetricsProto.WifiLog.SCAN_UNKNOWN, mPendingScans.size());
// notify and cancel failed scans
sendOpFailedToAllAndClear(mPendingScans, WifiScanner.REASON_UNSPECIFIED,
"Failed to start single scan");
}
}
8、WifiScannerImpl–>WificondScannerImpl
public abstract boolean startSingleScan(WifiNative.ScanSettings settings,
WifiNative.ScanEventHandler eventHandler);
9、WificondScannerImpl–>WifiNative
public boolean startSingleScan(WifiNative.ScanSettings settings,
WifiNative.ScanEventHandler eventHandler) {
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);
}
return true;
}
}
10、WifiNative–>WificondControl
public boolean scan(
@NonNull String ifaceName, int scanType, Set<Integer> freqs,
Set<String> hiddenNetworkSSIDs) {
return mWificondControl.scan(ifaceName, scanType, freqs, hiddenNetworkSSIDs);
}
11、WificondControl–>scanner_impl.cpp
public boolean scan(@NonNull String ifaceName,
int scanType,
Set<Integer> freqs,
Set<String> hiddenNetworkSSIDs) {
............
try {
return scannerImpl.scan(settings);
} catch (RemoteException e1) {
Log.e(TAG, "Failed to request scan due to remote exception");
}
return false;
}
12、scanner_impl.cpp–>scan_utils.cpp
Status ScannerImpl::scan(const SingleScanSettings& scan_settings,
bool* out_success) {
................
int error_code = 0;
if (!scan_utils_->Scan(interface_index_, request_random_mac, scan_type,
ssids, freqs, &error_code)) {
CHECK(error_code != ENODEV) << "Driver is in a bad state, restarting wificond";
*out_success = false;
return Status::ok();
}
}
13、scan_utils.cpp
scan_utils 通过netlink 将 NL80211_CMD_TRIGGER_SCAN传递wpa_supplicant(driver_nl80211_event.c)
bool ScanUtils::Scan(uint32_t interface_index,
bool request_random_mac,
int scan_type,
const vector<vector<uint8_t>>& ssids,
const vector<uint32_t>& freqs,
int* error_code) {
NL80211Packet trigger_scan(
netlink_manager_->GetFamilyId(),
NL80211_CMD_TRIGGER_SCAN,
netlink_manager_->GetSequenceNumber(),
getpid());
trigger_scan.AddFlag(NLM_F_ACK);
NL80211Attr<uint32_t> if_index_attr(NL80211_ATTR_IFINDEX, interface_index);
NL80211NestedAttr ssids_attr(NL80211_ATTR_SCAN_SSIDS);
for (size_t i = 0; i < ssids.size(); i++) {
ssids_attr.AddAttribute(NL80211Attr<vector<uint8_t>>(i, ssids[i]));
}
NL80211NestedAttr freqs_attr(NL80211_ATTR_SCAN_FREQUENCIES);
for (size_t i = 0; i < freqs.size(); i++) {
freqs_attr.AddAttribute(NL80211Attr<uint32_t>(i, freqs[i]));
}
trigger_scan.AddAttribute(if_index_attr);
trigger_scan.AddAttribute(ssids_attr);
// An absence of NL80211_ATTR_SCAN_FREQUENCIES attribue informs kernel to
// scan all supported frequencies.
if (!freqs.empty()) {
trigger_scan.AddAttribute(freqs_attr);
}
uint32_t scan_flags = 0;
if (request_random_mac) {
scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR;
}
switch (scan_type) {
case IWifiScannerImpl::SCAN_TYPE_LOW_SPAN:
scan_flags |= NL80211_SCAN_FLAG_LOW_SPAN;
break;
case IWifiScannerImpl::SCAN_TYPE_LOW_POWER:
scan_flags |= NL80211_SCAN_FLAG_LOW_POWER;
break;
case IWifiScannerImpl::SCAN_TYPE_HIGH_ACCURACY:
scan_flags |= NL80211_SCAN_FLAG_HIGH_ACCURACY;
break;
case IWifiScannerImpl::SCAN_TYPE_DEFAULT:
break;
default:
CHECK(0) << "Invalid scan type received: " << scan_type;
}
if (scan_flags) {
trigger_scan.AddAttribute(
NL80211Attr<uint32_t>(NL80211_ATTR_SCAN_FLAGS,
scan_flags));
}
vector<unique_ptr<const NL80211Packet>> response;
if (!netlink_manager_->SendMessageAndGetAckOrError(trigger_scan,
error_code)) {
// Logging is done inside |SendMessageAndGetAckOrError|.
return false;
}
return true;
}
14、扫描结果回传
WificondControl.OnScanResultReady 上报 WifiMonitor
WifiMonitor -> WificondScannerImpl -> WifiScaningServiceImpl->
WifiScaningServiceImpl ->WifiService --> WifiTracker --> WifiSettings 刷新扫描结果
关注公众号,获取更多开发必备知识