搞openharmony的公司黄掉了,做回android了,惨!
Android13 wifi模块移动到/package/modules中了
├── WifiDialog
├── apex
├── framework
└── service
以扫描流程为例:
IWifiManager.aidl
这里是提供给上层的api:
boolean startScan(String packageName, String featureId);
WifiServiceImpl是IWifiManager这个binder的服务端:
WifiServiceImpl.java
public boolean startScan(String packageName, String featureId) {
if (enforceChangePermission(packageName) != MODE_ALLOWED) {
return false;
}
int callingUid = Binder.getCallingUid();
mWifiPermissionsUtil.checkPackage(callingUid, packageName);
long ident = Binder.clearCallingIdentity();
mLog.info("startScan uid=%").c(callingUid).flush();
synchronized (this) {
if (mInIdleMode) {
// Need to send an immediate scan result broadcast in case the
// caller is waiting for a result ..
// TODO: investigate if the logic to cancel scans when idle can move to
// WifiScanningServiceImpl. This will 1 - clean up WifiServiceImpl and 2 -
// avoid plumbing an awkward path to report a cancelled/failed scan. This will
// be sent directly until b/31398592 is fixed.
sendFailedScanBroadcast();
mScanPending = true;
return false;
}
}
try {
mWifiPermissionsUtil.enforceCanAccessScanResults(packageName, featureId, callingUid,
null);
Boolean scanSuccess = mWifiThreadRunner.call(() ->
mScanRequestProxy.startScan(callingUid, packageName), null);
if (scanSuccess == null) {
sendFailedScanBroadcast();
return false;
}
if (!scanSuccess) {
Log.e(TAG, "Failed to start scan");
return false;
}
} catch (SecurityException e) {
Log.w(TAG, "Permission violation - startScan not allowed for"
+ " uid=" + callingUid + ", packageName=" + packageName + ", reason=" + e);
return false;
} finally {
Binder.restoreCallingIdentity(ident);
}
return true;
}
ScanRequestProxy.java
public boolean startScan(int callingUid, String packageName) {
if (!mScanningEnabled || !retrieveWifiScannerIfNecessary()) {
Log.e(TAG, "Failed to retrieve wifiscanner");
sendScanResultFailureBroadcastToPackage(packageName);
return false;
}
boolean fromSettingsOrSetupWizard =
mWifiPermissionsUtil.checkNetworkSettingsPermission(callingUid)
|| mWifiPermissionsUtil.checkNetworkSetupWizardPermission(callingUid);
// Check and throttle scan request unless,
// a) App has either NETWORK_SETTINGS or NETWORK_SETUP_WIZARD permission.
// b) Throttling has been disabled by user.
int packageImportance = getPackageImportance(callingUid, packageName);
if (!fromSettingsOrSetupWizard && mThrottleEnabled
&& shouldScanRequestBeThrottledForApp(callingUid, packageName, packageImportance)) {
Log.i(TAG, "Scan request from " + packageName + " throttled");
sendScanResultFailureBroadcastToPackage(packageName);
return false;
}
// Create a worksource using the caller's UID.
WorkSource workSource = new WorkSource(callingUid, packageName);
mWifiMetrics.getScanMetrics().setWorkSource(workSource);
mWifiMetrics.getScanMetrics().setImportance(packageImportance);
// 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.SCAN_TYPE_HIGH_ACCURACY;
} else {
if (SdkLevel.isAtLeastS()) {
// since the scan request is from a normal app, do not scan all 6Ghz channels.
settings.set6GhzPscOnlyEnabled(true);
}
}
settings.band = WifiScanner.WIFI_BAND_ALL;
settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
| WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
if (mScanningForHiddenNetworksEnabled) {
settings.hiddenNetworks.clear();
// retrieve the list of hidden network SSIDs from saved network to scan for, if enabled.
settings.hiddenNetworks.addAll(mWifiConfigManager.retrieveHiddenNetworkList(false));
// retrieve the list of hidden network SSIDs from Network suggestion to scan for.
settings.hiddenNetworks.addAll(
mWifiInjector.getWifiNetworkSuggestionsManager()
.retrieveHiddenNetworkList(false));
}
mWifiScanner.startScan(settings, new HandlerExecutor(mHandler),
new ScanRequestProxyScanListener(), workSource);
return true;
}
WifiScaner.java
public void startScan(ScanSettings settings, @Nullable @CallbackExecutor Executor executor,
ScanListener listener, WorkSource workSource) {
Objects.requireNonNull(listener, "listener cannot be null");
int key = addListener(listener, executor);
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);
scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getAttributionTag());
mAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams);
}
AsyncChannel是一个作为Handler之间的通道,我们看这个asyncchannel定义的地方:
public WifiScanner(@NonNull Context context, @NonNull IWifiScanner service,
@NonNull Looper looper) {
mContext = context;
mService = service;
Messenger messenger = null;
try {
messenger = mService.getMessenger(); // 获取WifiScanningServiceImpl中包含mClientHandler的Messenger
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
if (messenger == null) {
throw new IllegalStateException("getMessenger() returned null! This is invalid.");
}
mAsyncChannel = new AsyncChannel();
mInternalHandler = new ServiceHandler(looper);
mAsyncChannel.connectSync(mContext, mInternalHandler, messenger);
// We cannot use fullyConnectSync because it sends the FULL_CONNECTION message
// synchronously, which causes WifiScanningService to receive the wrong replyTo value.
mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
}
WifiScanner在初始化的时候,绑定了WifiScanningServiceImpl中的包含mClientHandle的messenger,发message到clienthanle,然后由WifiSingleScanStateMachine状态机处理
WifiScanningServiceImpl.java
case WifiScanner.CMD_START_SINGLE_SCAN:
case WifiScanner.CMD_STOP_SINGLE_SCAN:
mSingleScanStateMachine.sendMessage(Message.obtain(msg));
break;
private void handleScanStartMessage(ClientInfo ci, Message msg) {
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;
}
ScanSettings scanSettings = null;
WorkSource workSource = null;
try {
scanSettings =
scanParams.getParcelable(
WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY);
workSource =
scanParams.getParcelable(
WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY);
} catch (BadParcelableException e) {
Log.wtf(TAG, "Failed to get parcelable params", e);
logCallback("singleScanInvalidRequest", ci, handler,
"bad parcel params");
replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST,
"bad parcel params");
return;
}
if (validateScanRequest(ci, handler, scanSettings)) {
if (getCurrentState() == mDefaultState && !scanSettings.ignoreLocationSettings) {
// Reject regular scan requests if scanning is disabled.
replyFailed(msg, WifiScanner.REASON_UNSPECIFIED, "not available");
return;
}
mWifiMetrics.incrementOneshotScanCount();
if ((scanSettings.band & WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY) != 0) {
mWifiMetrics.incrementOneshotScanWithDfsCount();
}
logScanRequest("addSingleScanRequest", ci, handler, workSource,
scanSettings, null);
replySucceeded(msg);
if (scanSettings.ignoreLocationSettings) {
// Inform wifi manager that an emergency scan is in progress (regardless of
// whether scanning is currently enabled or not). This ensures that
// the wifi chip remains on for the duration of this scan.
mWifiManager.setEmergencyScanRequestInProgress(true);
}
if (getCurrentState() == mScanningState) {
// 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 (activeScanSatisfies(scanSettings)) {
mActiveScans.addRequest(ci, handler, workSource, scanSettings);
} else {
mPendingScans.addRequest(ci, handler, workSource, scanSettings);
}
} else if (getCurrentState() == mIdleState) {
// 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.
mPendingScans.addRequest(ci, handler, workSource, scanSettings);
tryToStartNewScan();
} else if (getCurrentState() == mDefaultState) {
// If scanning is disabled and the request is for emergency purposes
// (checked above), add to pending list. this scan will be scheduled when
// transitioning to IdleState when wifi manager enables scanning as a part of
// processing WifiManager.setEmergencyScanRequestInProgress(true)
mPendingScans.addRequest(ci, handler, workSource, scanSettings);
}
} else {
logCallback("singleScanInvalidRequest", ci, handler, "bad request");
replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "bad request");
mWifiMetrics.incrementScanReturnEntry(
WifiMetricsProto.WifiLog.SCAN_FAILURE_INVALID_CONFIGURATION, 1);
}
}
后续一直调用到tracker的startsingleScan
public boolean startSingleScan(WifiNative.ScanSettings scanSettings) {
mStatusPerImpl.clear();
boolean anySuccess = false;
for (Map.Entry<String, WifiScannerImpl> entry : mScannerImpls.entrySet()) {
String ifaceName = entry.getKey();
WifiScannerImpl impl = entry.getValue();
boolean success = impl.startSingleScan(
scanSettings, new ScanEventHandler(ifaceName));
if (!success) {
Log.e(TAG, "Failed to start single scan on " + ifaceName);
mStatusPerImpl.put(ifaceName, STATUS_FAILED);
continue;
}
mStatusPerImpl.put(ifaceName, STATUS_PENDING);
anySuccess = true;
}
return anySuccess;
}
顺着impl.startSingleScan一路找,最终在WifiNl80211Manager.java
public boolean startScan(@NonNull String ifaceName, @WifiAnnotations.ScanType int scanType,
@SuppressLint("NullableCollection") @Nullable Set<Integer> freqs,
@SuppressLint("NullableCollection") @Nullable List<byte[]> hiddenNetworkSSIDs,
@SuppressLint("NullableCollection") @Nullable Bundle extraScanningParams) {
IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
if (scannerImpl == null) {
Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName);
return false;
}
SingleScanSettings settings = new SingleScanSettings();
try {
settings.scanType = getScanType(scanType);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Invalid scan type ", e);
return false;
}
settings.channelSettings = new ArrayList<>();
settings.hiddenNetworks = new ArrayList<>();
if (extraScanningParams != null) {
settings.enable6GhzRnr = extraScanningParams.getBoolean(SCANNING_PARAM_ENABLE_6GHZ_RNR);
}
if (freqs != null) {
for (Integer freq : freqs) {
ChannelSettings channel = new ChannelSettings();
channel.frequency = freq;
settings.channelSettings.add(channel);
}
}
if (hiddenNetworkSSIDs != null) {
for (byte[] ssid : hiddenNetworkSSIDs) {
HiddenNetwork network = new HiddenNetwork();
network.ssid = ssid;
// settings.hiddenNetworks is expected to be very small, so this shouldn't cause
// any performance issues.
if (!settings.hiddenNetworks.contains(network)) {
settings.hiddenNetworks.add(network);
}
}
}
try {
return scannerImpl.scan(settings);
} catch (RemoteException e1) {
Log.e(TAG, "Failed to request scan due to remote exception");
}
return false;
}
scannerImpl.scan(settings)这里通过aidl调用c++的服务,这里的流程也不复杂,就是打包,然后通过netlink将NL80211_CMD_TRIGGER_SCAN发送到内核
bool ScanUtils::Scan(uint32_t interface_index,
bool request_random_mac,
const vector<vector<uint8_t>>& ssids,
const vector<uint32_t>& freqs,
int* error_code) {
NL80211Packet trigger_scan(
netlink_manager_->GetFamilyId(),
NL80211_CMD_TRIGGER_SCAN, // event
netlink_manager_->GetSequenceNumber(),
getpid());
// If we do not use NLM_F_ACK, we only receive a unicast repsonse
// when there is an error. If everything is good, scan results notification
// will only be sent through multicast.
// If NLM_F_ACK is set, there will always be an unicast repsonse, either an
// ERROR or an ACK message. The handler will always be called and removed by
// NetlinkManager.
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);
}
if (request_random_mac) {
trigger_scan.AddAttribute(
NL80211Attr<uint32_t>(NL80211_ATTR_SCAN_FLAGS,
NL80211_SCAN_FLAG_RANDOM_ADDR));
}
// We are receiving an ERROR/ACK message instead of the actual
// scan results here, so it is OK to expect a timely response because
// kernel is supposed to send the ERROR/ACK back before the scan starts.
vector<unique_ptr<const NL80211Packet>> response;
if (!netlink_manager_->SendMessageAndGetAckOrError(trigger_scan,
error_code)) {
// Logging is done inside |SendMessageAndGetAckOrError|.
return false;
}
if (*error_code != 0) {
LOG(ERROR) << "NL80211_CMD_TRIGGER_SCAN failed: " << strerror(*error_code);
return false;
}
return true;
}
bool NetlinkManager::SendMessageInternal(const NL80211Packet& packet, int fd,
InterceptedSocket nl_destination) {
const vector<uint8_t>& data = packet.GetConstData();
struct sockaddr_nl sa = nl_destination;
ssize_t bytes_sent = TEMP_FAILURE_RETRY(
sendto(fd, data.data(), data.size(), 0, reinterpret_cast<struct sockaddr*>(&sa), sizeof(sa))
);
if (bytes_sent == -1) {
PLOG(ERROR) << "Failed to send netlink message";
CHECK(!nlinterceptor::isEnabled()) << "Interceptor died, restarting wificond...";
return false;
}
return true;
}