版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/huangweiqing80/article/details/82388382
1.上节分析到frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java
class InitialState extends State
case CMD_START_SUPPLICANT:
mClientInterface = mWifiNative.setupForClientMode(); // loadDriver
mWifiNative.enableSupplicant() // start supplicant
transitionTo(mSupplicantStartingState);
2.mWifiNative.enableSupplicant() –>
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
public boolean enableSupplicant() {
return mWificondControl.enableSupplicant();
}
3.mWificondControl.enableSupplicant(); –>
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.java
private IClientInterface mClientInterface;
...
public boolean enableSupplicant() {
if (mClientInterface == null) {
Log.e(TAG, "No valid wificond client interface handler");
return false;
}
try {
return mClientInterface.enableSupplicant();
} catch (RemoteException e) {
Log.e(TAG, "Failed to enable supplicant due to remote exception");
}
return false;
}
mClientInterface对象是在WificondControl.java中得到
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.java
public IClientInterface setupDriverForClientMode() {
Log.d(TAG, "Setting up driver for client mode");
mWificond = mWifiInjector.makeWificond();
if (mWificond == null) {
Log.e(TAG, "Failed to get reference to wificond");
return null;
}
IClientInterface clientInterface = null;
try {
clientInterface = mWificond.createClientInterface();
} 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
mClientInterface = clientInterface;
4.mClientInterface对应的实现是在client_interface_binder,所以上面的mClientInterface.enableSupplicant() –>
system/connectivity/wificond/client_interface_binder.cpp
Status ClientInterfaceBinder::enableSupplicant(bool* success) {
*success = impl_ && impl_->EnableSupplicant();
return Status::ok();
}
而impl_对应的是client_interface_impl.
在ClientInterfaceBinder类中:
class ClientInterfaceBinder : public android::net::wifi::BnClientInterface {
…
private:
ClientInterfaceImpl* impl_;
5.impl_->EnableSupplicant()对应的实现是
system/connectivity/wificond/client_interface_impl.cpp
bool ClientInterfaceImpl::EnableSupplicant() {
return supplicant_manager_->StartSupplicant();
}
其中supplicant_manager_是在client_interface_impl的构造函数中初始化的
ClientInterfaceImpl::ClientInterfaceImpl(
uint32_t wiphy_index,
const std::string& interface_name,
uint32_t interface_index,
const std::vector<uint8_t>& interface_mac_addr,
InterfaceTool* if_tool,
SupplicantManager* supplicant_manager,
NetlinkUtils* netlink_utils,
ScanUtils* scan_utils)
: wiphy_index_(wiphy_index),
interface_name_(interface_name),
interface_index_(interface_index),
interface_mac_addr_(interface_mac_addr),
if_tool_(if_tool),
supplicant_manager_(supplicant_manager),
client_interface_impl的构造函数,是在server里调用的
Status Server::createClientInterface(sp<IClientInterface>* created_interface) {
InterfaceInfo interface;
if (!SetupInterface(&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(),
supplicant_manager_.get(),
netlink_utils_,
scan_utils_));
*created_interface = client_interface->GetBinder();
client_interfaces_.push_back(std::move(client_interface));
BroadcastClientInterfaceReady(client_interfaces_.back()->GetBinder());
return Status::ok();
}
6.supplicant_manager_->StartSupplicant()的实现是
/frameworks/opt/net/wifi/libwifi_system/supplicant_manager.cpp
bool SupplicantManager::StartSupplicant() {
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
int count = 200; /* wait at most 20 seconds for completion */
const prop_info* pi;
unsigned serial = 0;
/* Check whether already running */
if (property_get(kSupplicantInitProperty, supp_status, NULL) &&
strcmp(supp_status, "running") == 0) {
return true;
}
/* Before starting the daemon, make sure its config file exists */
if (ensure_config_file_exists(kSupplicantConfigFile) < 0) {
LOG(ERROR) << "Wi-Fi will not be enabled";
return false;
}
/*
* Some devices have another configuration file for the p2p interface.
* However, not all devices have this, and we'll let it slide if it
* is missing. For devices that do expect this file to exist,
* supplicant will refuse to start and emit a good error message.
* No need to check for it here.
*/
(void)ensure_config_file_exists(kP2pConfigFile);
/*
* Get a reference to the status property, so we can distinguish
* the case where it goes stopped => running => stopped (i.e.,
* it start up, but fails right away) from the case in which
* it starts in the stopped state and never manages to start
* running at all.
*/
pi = __system_property_find(kSupplicantInitProperty);
if (pi != NULL) {
serial = __system_property_serial(pi);
}
property_set("ctl.start", kSupplicantServiceName);
sched_yield();
while (count-- > 0) {
if (pi == NULL) {
pi = __system_property_find(kSupplicantInitProperty);
}
if (pi != NULL) {
/*
* property serial updated means that init process is scheduled
* after we sched_yield, further property status checking is based on this
*/
if (__system_property_serial(pi) != serial) {
__system_property_read(pi, NULL, supp_status);
if (strcmp(supp_status, "running") == 0) {
return true;
} else if (strcmp(supp_status, "stopped") == 0) {
return false;
}
}
}
usleep(100000);
}
return false;
}
可以观察到这个方法会先检查配置文件是否存在
const char kSupplicantInitProperty[] = "init.svc.wpa_supplicant";
const char kSupplicantConfigTemplatePath[] =
"/etc/wifi/wpa_supplicant.conf";
const char kSupplicantConfigFile[] = "/data/misc/wifi/wpa_supplicant.conf";
const char kP2pConfigFile[] = "/data/misc/wifi/p2p_supplicant.conf";
const char kSupplicantServiceName[] = "wpa_supplicant";
constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
之后通过 “setprop ctrl.start wpa_supplicant” 来触发init进程去fork一个子进程来完成supplicant的启动。
看最后的注释:
/*
* property serial updated means that init process is scheduled
* after we sched_yield, further property status checking is based on this
*/
表示调用了sched_yield后start wpa_supplicant的任务就进入时刻表中,后续基于此进行属性状态检查supplicant是否启动完成。
7.所以wpa_supplicant最后的启动就是:
通过启动init.rc中的服务
service wpa_supplicant /system/bin/wpa_supplicant \
-iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
-I/system/etc/wifi/p2p_supplicant_overlay.conf \
-O/data/misc/wifi/sockets \
-m/data/misc/wifi/p2p_supplicant.conf \
-puse_p2p_group_interface=1p2p_device=1 \
-e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0
class main
socket wpa_wlan0 dgram 660 wifi wifi
disabled
oneshot
下面是enableSupplicant的一张流程图: