1.回顾
之前在(一百四十八)Android P wifi启动过程中的sta interface创建 中梳理了sta interface的创建流程,之后还有
if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) {
Log.e(TAG, "Failed to setup iface in wificond on " + iface);
teardownInterface(iface.name);
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
return null;
}
if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {
Log.e(TAG, "Failed to setup iface in supplicant on " + iface);
teardownInterface(iface.name);
mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
return null;
}
先梳理下WificondControl的setupInterfaceForClientMode
2.流程梳理
WificondControl
/**
* Setup interface for client mode via wificond.
* @return An IClientInterface as wificond client interface binder handler.
* Returns null on failure.
*/
public IClientInterface setupInterfaceForClientMode(@NonNull String ifaceName) {
Log.d(TAG, "Setting up interface for client mode");
if (!retrieveWificondAndRegisterForDeath()) {
return null;
}
IClientInterface clientInterface = null;
try {
clientInterface = mWificond.createClientInterface(ifaceName);
} catch (RemoteException e1) {
Log.e(TAG, "Failed to get IClientInterface due to remote exception");
return null;
}
if (clientInterface == null) {
Log.e(TAG, "Could not get IClientInterface instance from wificond");
return null;
}
Binder.allowBlocking(clientInterface.asBinder());
// Refresh Handlers
mClientInterfaces.put(ifaceName, clientInterface);
try {
IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl();
if (wificondScanner == null) {
Log.e(TAG, "Failed to get WificondScannerImpl");
return null;
}
mWificondScanners.put(ifaceName, wificondScanner);
Binder.allowBlocking(wificondScanner.asBinder());
ScanEventHandler scanEventHandler = new ScanEventHandler(ifaceName);
mScanEventHandlers.put(ifaceName, scanEventHandler);
wificondScanner.subscribeScanEvents(scanEventHandler);
PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(ifaceName);
mPnoScanEventHandlers.put(ifaceName, pnoScanEventHandler);
wificondScanner.subscribePnoScanEvents(pnoScanEventHandler);
} catch (RemoteException e) {
Log.e(TAG, "Failed to refresh wificond scanner due to remote exception");
}
return clientInterface;
}
system/connectivity/wificond/server.cpp
Status Server::createClientInterface(const std::string& iface_name,
sp<IClientInterface>* created_interface) {
InterfaceInfo interface;
if (!SetupInterface(iface_name, &interface)) {
return Status::ok(); // Logging was done internally
}
unique_ptr<ClientInterfaceImpl> client_interface(new ClientInterfaceImpl(
wiphy_index_,
interface.name,
interface.index,
interface.mac_address,
if_tool_.get(),
netlink_utils_,
scan_utils_));
*created_interface = client_interface->GetBinder();
BroadcastClientInterfaceReady(client_interface->GetBinder());
client_interfaces_[iface_name] = std::move(client_interface);
return Status::ok();
}
bool Server::SetupInterface(const std::string& iface_name,
InterfaceInfo* interface) {
if (!RefreshWiphyIndex()) {
return false;
}
netlink_utils_->SubscribeRegDomainChange(
wiphy_index_,
std::bind(&Server::OnRegDomainChanged,
this,
_1));
interfaces_.clear();
if (!netlink_utils_->GetInterfaces(wiphy_index_, &interfaces_)) {
LOG(ERROR) << "Failed to get interfaces info from kernel";
return false;
}
for (const auto& iface : interfaces_) {
if (iface.name == iface_name) {
*interface = iface;
return true;
}
}
LOG(ERROR) << "No usable interface found";
return false;
}
这边会从kernel获取所有的interface,然后对照name看有没有对应的,如果有的话,返回一个对应的iface.
看下interfaces是何时初始化的
netlink_utils_
bool NetlinkUtils::GetInterfaces(uint32_t wiphy_index,
vector<InterfaceInfo>* interface_info) {
NL80211Packet get_interfaces(
netlink_manager_->GetFamilyId(),
NL80211_CMD_GET_INTERFACE,
netlink_manager_->GetSequenceNumber(),
getpid());
get_interfaces.AddFlag(NLM_F_DUMP);
get_interfaces.AddAttribute(
NL80211Attr<uint32_t>(NL80211_ATTR_WIPHY, wiphy_index));
vector<unique_ptr<const NL80211Packet>> response;
if (!netlink_manager_->SendMessageAndGetResponses(get_interfaces, &response)) {
LOG(ERROR) << "NL80211_CMD_GET_INTERFACE dump failed";
return false;
}
if (response.empty()) {
LOG(ERROR) << "No interface is found";
return false;
}
for (auto& packet : response) {
if (packet->GetMessageType() == NLMSG_ERROR) {
LOG(ERROR) << "Receive ERROR message: "
<< strerror(packet->GetErrorCode());
return false;
}
if (packet->GetMessageType() != netlink_manager_->GetFamilyId()) {
LOG(ERROR) << "Wrong message type for new interface message: "
<< packet->GetMessageType();
return false;
}
if (packet->GetCommand() != NL80211_CMD_NEW_INTERFACE) {
LOG(ERROR) << "Wrong command in response to "
<< "an interface dump request: "
<< static_cast<int>(packet->GetCommand());
return false;
}
// In some situations, it has been observed that the kernel tells us
// about a pseudo interface that does not have a real netdev. In this
// case, responses will have a NL80211_ATTR_WDEV, and not the expected
// IFNAME/IFINDEX. In this case we just skip these pseudo interfaces.
uint32_t if_index;
if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
LOG(DEBUG) << "Failed to get interface index";
continue;
}
// Today we don't check NL80211_ATTR_IFTYPE because at this point of time
// driver always reports that interface is in STATION mode. Even when we
// are asking interfaces infomation on behalf of tethering, it is still so
// because hostapd is supposed to set interface to AP mode later.
string if_name;
if (!packet->GetAttributeValue(NL80211_ATTR_IFNAME, &if_name)) {
LOG(WARNING) << "Failed to get interface name";
continue;
}
vector<uint8_t> if_mac_addr;
if (!packet->GetAttributeValue(NL80211_ATTR_MAC, &if_mac_addr)) {
LOG(WARNING) << "Failed to get interface mac address";
continue;
}
interface_info->emplace_back(if_index, if_name, if_mac_addr);
}
return true;
}
通过netlink_manager_发送包,然后依次解析返回回来的包得到if_index/if_name/if_mac_addr压栈到interface_info,最后封装成一个client_interface
这流程很熟悉,之前在(五十七)Android O WiFi的扫描流程梳理续——梳理java与c++之间的aidl-cpp通信 梳理过
这边相当于搭好了从上到kernel的通信道路,这时sta iface应该已经确实创建好了,感觉中间哪里看漏了一步。
3.总结
WificondControl的setupInterfaceForClientMode看起来就是在wificond初始化一下interface的通信,获取可以和kernel通信的接口,方便下发scan命令