Android O enableSupplicant分析

版权声明:本文为博主原创文章,未经博主允许不得转载。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的一张流程图:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/huangweiqing80/article/details/82388382