1.流程回顾

之前在(一百四十八)Android P wifi启动过程中的sta interface创建 中梳理了sta interface的创建流程,在(一百四十九)Android P WificondControl的setupInterfaceForClientMode梳理了wificond的setup interface,在(一百五十)Android P SupplicantStaIfaceHal的setupIface SupplicantStaIfaceHal的setupIface

但都没有找到sta iface真正创建的地方,又回头梳理了一遍终于找到了。

真正创建的地方还是(一百五十)Android P SupplicantStaIfaceHal的setupIface SupplicantStaIfaceHal的setupIface

后续分析补充,下面分析的不对

2.流程梳理

2.1 supplicant.cpp

wpa_supplicant_add_iface

std::pair<SupplicantStatus, sp<ISupplicantIface>>
Supplicant::addInterfaceInternal(const IfaceInfo& iface_info)
{android::sp<ISupplicantIface> iface;// Check if required |ifname| argument is empty.if (iface_info.name.empty()) {return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};}// Try to get the wpa_supplicant record for this iface, return// the iface object with the appropriate status code if it exists.SupplicantStatus status;std::tie(status, iface) = getInterfaceInternal(iface_info);if (status.code == SupplicantStatusCode::SUCCESS) {return {{SupplicantStatusCode::FAILURE_IFACE_EXISTS, ""},iface};}struct wpa_interface iface_params = {};iface_params.driver = kIfaceDriverName;if (iface_info.type == IfaceType::P2P) {if (ensureConfigFileExists(kP2pIfaceConfPath, kOldP2pIfaceConfPath) != 0) {wpa_printf(MSG_ERROR, "Conf file does not exists: %s",kP2pIfaceConfPath);return {{SupplicantStatusCode::FAILURE_UNKNOWN,"Conf file does not exist"},{}};}iface_params.confname = kP2pIfaceConfPath;int ret = access(kP2pIfaceConfOverlayPath, R_OK);if (ret == 0) {iface_params.confanother = kP2pIfaceConfOverlayPath;}} else {if (ensureConfigFileExists(kStaIfaceConfPath, kOldStaIfaceConfPath) != 0) {wpa_printf(MSG_ERROR, "Conf file does not exists: %s",kStaIfaceConfPath);return {{SupplicantStatusCode::FAILURE_UNKNOWN,"Conf file does not exist"},{}};}iface_params.confname = kStaIfaceConfPath;int ret = access(kStaIfaceConfOverlayPath, R_OK);if (ret == 0) {iface_params.confanother = kStaIfaceConfOverlayPath;}}iface_params.ifname = iface_info.name.c_str();struct wpa_supplicant* wpa_s =wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);if (!wpa_s) {return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};}// The supplicant core creates a corresponding hidl object via// HidlManager when |wpa_supplicant_add_iface| is called.return getInterfaceInternal(iface_info);
}

2.2 wpa_supplicant.c

/*** wpa_supplicant_add_iface - Add a new network interface* @global: Pointer to global data from wpa_supplicant_init()* @iface: Interface configuration options* @parent: Parent interface or %NULL to assign new interface as parent* Returns: Pointer to the created interface or %NULL on failure** This function is used to add new network interfaces for %wpa_supplicant.* This can be called before wpa_supplicant_run() to add interfaces before the* main event loop has been started. In addition, new interfaces can be added* dynamically while %wpa_supplicant is already running. This could happen,* e.g., when a hotplug network adapter is inserted.*/
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,struct wpa_interface *iface,struct wpa_supplicant *parent)
{struct wpa_supplicant *wpa_s;struct wpa_interface t_iface;struct wpa_ssid *ssid;if (global == NULL || iface == NULL)return NULL;wpa_s = wpa_supplicant_alloc(parent);if (wpa_s == NULL)return NULL;wpa_s->global = global;t_iface = *iface;if (global->params.override_driver) {wpa_printf(MSG_DEBUG, "Override interface parameter: driver ""('%s' -> '%s')",iface->driver, global->params.override_driver);t_iface.driver = global->params.override_driver;}if (global->params.override_ctrl_interface) {wpa_printf(MSG_DEBUG, "Override interface parameter: ""ctrl_interface ('%s' -> '%s')",iface->ctrl_interface,global->params.override_ctrl_interface);t_iface.ctrl_interface =global->params.override_ctrl_interface;}if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {wpa_printf(MSG_DEBUG, "Failed to add interface %s",iface->ifname);wpa_supplicant_deinit_iface(wpa_s, 0, 0);return NULL;}/* Notify the control interfaces about new iface */if (wpas_notify_iface_added(wpa_s)) {wpa_supplicant_deinit_iface(wpa_s, 1, 0);return NULL;}/* Notify the control interfaces about new networks for non p2p mgmt* ifaces. */if (iface->p2p_mgmt == 0) {for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)wpas_notify_network_added(wpa_s, ssid);}wpa_s->next = global->ifaces;global->ifaces = wpa_s;wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);#ifdef CONFIG_P2Pif (wpa_s->global->p2p == NULL &&!wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&wpas_p2p_add_p2pdev_interface(wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {wpa_printf(MSG_INFO,"P2P: Failed to enable P2P Device interface");/* Try to continue without. P2P will be disabled. */}
#endif /* CONFIG_P2P */return wpa_s;
}

看下初始化的逻辑

static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,struct wpa_interface *iface)
{struct wpa_driver_capa capa;int capa_res;u8 dfs_domain;wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver ""'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,iface->confname ? iface->confname : "N/A",iface->driver ? iface->driver : "default",iface->ctrl_interface ? iface->ctrl_interface : "N/A",iface->bridge_ifname ? iface->bridge_ifname : "N/A");if (iface->confname) {
#ifdef CONFIG_BACKEND_FILEwpa_s->confname = os_rel2abs_path(iface->confname);if (wpa_s->confname == NULL) {wpa_printf(MSG_ERROR, "Failed to get absolute path ""for configuration file '%s'.",iface->confname);return -1;}wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",iface->confname, wpa_s->confname);
#else /* CONFIG_BACKEND_FILE */wpa_s->confname = os_strdup(iface->confname);
#endif /* CONFIG_BACKEND_FILE */wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);if (wpa_s->conf == NULL) {wpa_printf(MSG_ERROR, "Failed to read or parse ""configuration '%s'.", wpa_s->confname);return -1;}wpa_s->confanother = os_rel2abs_path(iface->confanother);wpa_config_read(wpa_s->confanother, wpa_s->conf);/** Override ctrl_interface and driver_param if set on command* line.*/if (iface->ctrl_interface) {os_free(wpa_s->conf->ctrl_interface);wpa_s->conf->ctrl_interface =os_strdup(iface->ctrl_interface);}if (iface->driver_param) {os_free(wpa_s->conf->driver_param);wpa_s->conf->driver_param =os_strdup(iface->driver_param);}if (iface->p2p_mgmt && !iface->ctrl_interface) {os_free(wpa_s->conf->ctrl_interface);wpa_s->conf->ctrl_interface = NULL;}} elsewpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,iface->driver_param);if (wpa_s->conf == NULL) {wpa_printf(MSG_ERROR, "\nNo configuration found.");return -1;}if (iface->ifname == NULL) {wpa_printf(MSG_ERROR, "\nInterface name is required.");return -1;}if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",iface->ifname);return -1;}os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));if (iface->bridge_ifname) {if (os_strlen(iface->bridge_ifname) >=sizeof(wpa_s->bridge_ifname)) {wpa_printf(MSG_ERROR, "\nToo long bridge interface ""name '%s'.", iface->bridge_ifname);return -1;}os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,sizeof(wpa_s->bridge_ifname));}/* RSNA Supplicant Key Management - INITIALIZE */eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);eapol_sm_notify_portValid(wpa_s->eapol, FALSE);/* Initialize driver interface and register driver event handler before* L2 receive handler so that association events are processed before* EAPOL-Key packets if both become available for the same select()* call. */if (wpas_init_driver(wpa_s, iface) < 0)return -1;if (wpa_supplicant_init_wpa(wpa_s) < 0)return -1;wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :NULL);wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,wpa_s->conf->dot11RSNAConfigPMKLifetime)) {wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for ""dot11RSNAConfigPMKLifetime");return -1;}if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for ""dot11RSNAConfigPMKReauthThreshold");return -1;}if (wpa_s->conf->dot11RSNAConfigSATimeout &&wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,wpa_s->conf->dot11RSNAConfigSATimeout)) {wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for ""dot11RSNAConfigSATimeout");return -1;}wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,&wpa_s->hw.num_modes,&wpa_s->hw.flags,&dfs_domain);if (wpa_s->hw.modes) {u16 i;for (i = 0; i < wpa_s->hw.num_modes; i++) {if (wpa_s->hw.modes[i].vht_capab) {wpa_s->hw_capab = CAPAB_VHT;break;}if (wpa_s->hw.modes[i].ht_capab &HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)wpa_s->hw_capab = CAPAB_HT40;else if (wpa_s->hw.modes[i].ht_capab &&wpa_s->hw_capab == CAPAB_NO_HT_VHT)wpa_s->hw_capab = CAPAB_HT;}}capa_res = wpa_drv_get_capa(wpa_s, &capa);if (capa_res == 0) {wpa_s->drv_capa_known = 1;wpa_s->drv_flags = capa.flags;wpa_s->drv_enc = capa.enc;wpa_s->drv_smps_modes = capa.smps_modes;wpa_s->drv_rrm_flags = capa.rrm_flags;wpa_s->probe_resp_offloads = capa.probe_resp_offloads;wpa_s->max_scan_ssids = capa.max_scan_ssids;wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;wpa_s->max_sched_scan_plan_interval =capa.max_sched_scan_plan_interval;wpa_s->max_sched_scan_plan_iterations =capa.max_sched_scan_plan_iterations;wpa_s->sched_scan_supported = capa.sched_scan_supported;wpa_s->max_match_sets = capa.max_match_sets;wpa_s->max_remain_on_chan = capa.max_remain_on_chan;wpa_s->max_stations = capa.max_stations;wpa_s->extended_capa = capa.extended_capa;wpa_s->extended_capa_mask = capa.extended_capa_mask;wpa_s->extended_capa_len = capa.extended_capa_len;wpa_s->num_multichan_concurrent =capa.num_multichan_concurrent;wpa_s->wmm_ac_supported = capa.wmm_ac_supported;if (capa.mac_addr_rand_scan_supported)wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;if (wpa_s->sched_scan_supported &&capa.mac_addr_rand_sched_scan_supported)wpa_s->mac_addr_rand_supported |=(MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);}if (wpa_s->max_remain_on_chan == 0)wpa_s->max_remain_on_chan = 1000;/** Only take p2p_mgmt parameters when P2P Device is supported.* Doing it here as it determines whether l2_packet_init() will be done* during wpa_supplicant_driver_init().*/if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)wpa_s->p2p_mgmt = iface->p2p_mgmt;elseiface->p2p_mgmt = 1;if (wpa_s->num_multichan_concurrent == 0)wpa_s->num_multichan_concurrent = 1;if (wpa_supplicant_driver_init(wpa_s) < 0)return -1;#ifdef CONFIG_TDLSif ((!iface->p2p_mgmt ||!(wpa_s->drv_flags &WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&wpa_tdls_init(wpa_s->wpa))return -1;
#endif /* CONFIG_TDLS */if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");return -1;}#ifdef CONFIG_FSTif (wpa_s->conf->fst_group_id) {struct fst_iface_cfg cfg;struct fst_wpa_obj iface_obj;fst_wpa_supplicant_fill_iface_obj(wpa_s, &iface_obj);os_strlcpy(cfg.group_id, wpa_s->conf->fst_group_id,sizeof(cfg.group_id));cfg.priority = wpa_s->conf->fst_priority;cfg.llt = wpa_s->conf->fst_llt;wpa_s->fst = fst_attach(wpa_s->ifname, wpa_s->own_addr,&iface_obj, &cfg);if (!wpa_s->fst) {wpa_msg(wpa_s, MSG_ERROR,"FST: Cannot attach iface %s to group %s",wpa_s->ifname, cfg.group_id);return -1;}}
#endif /* CONFIG_FST */if (wpas_wps_init(wpa_s))return -1;#ifdef CONFIG_GAS_SERVERwpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);if (!wpa_s->gas_server) {wpa_printf(MSG_ERROR, "Failed to initialize GAS server");return -1;}
#endif /* CONFIG_GAS_SERVER */#ifdef CONFIG_DPPif (wpas_dpp_init(wpa_s) < 0)return -1;
#endif /* CONFIG_DPP */if (wpa_supplicant_init_eapol(wpa_s) < 0)return -1;wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);if (wpa_s->ctrl_iface == NULL) {wpa_printf(MSG_ERROR,"Failed to initialize control interface '%s'.\n""You may have another wpa_supplicant process ""already running or the file was\n""left by an unclean termination of wpa_supplicant ""in which case you will need\n""to manually remove this file before starting ""wpa_supplicant again.\n",wpa_s->conf->ctrl_interface);return -1;}wpa_s->gas = gas_query_init(wpa_s);if (wpa_s->gas == NULL) {wpa_printf(MSG_ERROR, "Failed to initialize GAS query");return -1;}if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");return -1;}if (wpa_bss_init(wpa_s) < 0)return -1;#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
#ifdef CONFIG_MESHdl_list_init(&wpa_s->mesh_external_pmksa_cache);
#endif /* CONFIG_MESH */
#endif /* CONFIG_PMKSA_CACHE_EXTERNAL *//** Set Wake-on-WLAN triggers, if configured.* Note: We don't restore/remove the triggers on shutdown (it doesn't* have effect anyway when the interface is down).*/if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)return -1;#ifdef CONFIG_EAP_PROXY
{size_t len;wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1,wpa_s->imsi, &len);if (wpa_s->mnc_len > 0) {wpa_s->imsi[len] = '\0';wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",wpa_s->imsi, wpa_s->mnc_len);} else {wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");}
}
#endif /* CONFIG_EAP_PROXY */if (pcsc_reader_init(wpa_s) < 0)return -1;if (wpas_init_ext_pw(wpa_s) < 0)return -1;wpas_rrm_reset(wpa_s);wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);#ifdef CONFIG_HS20hs20_init(wpa_s);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBOif (wpa_s->conf->oce) {if ((wpa_s->conf->oce & OCE_STA) &&(wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA))wpa_s->enable_oce = OCE_STA;if ((wpa_s->conf->oce & OCE_STA_CFON) &&(wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) {/* TODO: Need to add STA-CFON support */wpa_printf(MSG_ERROR,"OCE STA-CFON feature is not yet supported");}}wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
#endif /* CONFIG_MBO */wpa_supplicant_set_default_scan_ies(wpa_s);return 0;
}

看下这段逻辑

 /* Initialize driver interface and register driver event handler before* L2 receive handler so that association events are processed before* EAPOL-Key packets if both become available for the same select()* call. */if (wpas_init_driver(wpa_s, iface) < 0)return -1;static int wpas_init_driver(struct wpa_supplicant *wpa_s,struct wpa_interface *iface)
{const char *ifname, *driver, *rn;driver = iface->driver;
next_driver:if (wpa_supplicant_set_driver(wpa_s, driver) < 0)return -1;wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);if (wpa_s->drv_priv == NULL) {const char *pos;pos = driver ? os_strchr(driver, ',') : NULL;if (pos) {wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize ""driver interface - try next driver wrapper");driver = pos + 1;goto next_driver;}wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver ""interface");return -1;}if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected ""driver_param '%s'", wpa_s->conf->driver_param);return -1;}ifname = wpa_drv_get_ifname(wpa_s);if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced ""interface name with '%s'", ifname);os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));}rn = wpa_driver_get_radio_name(wpa_s);if (rn && rn[0] == '\0')rn = NULL;wpa_s->radio = radio_add_interface(wpa_s, rn);if (wpa_s->radio == NULL)return -1;return 0;
}

2.3 driver.h

/* driver_ops */
static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s,const char *ifname)
{if (wpa_s->driver->init2)return wpa_s->driver->init2(wpa_s, ifname,wpa_s->global_drv_priv);if (wpa_s->driver->init) {return wpa_s->driver->init(wpa_s, ifname);}return NULL;
}

搜了下有对init2的初始化./src/drivers/driver_nl80211.c:10360:    .init2 = wpa_driver_nl80211_init

/*** wpa_driver_nl80211_init - Initialize nl80211 driver interface* @ctx: context to be used when calling wpa_supplicant functions,* e.g., wpa_supplicant_event()* @ifname: interface name, e.g., wlan0* @global_priv: private driver global data from global_init()* Returns: Pointer to private data, %NULL on failure*/
static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,void *global_priv)
{return wpa_driver_nl80211_drv_init(ctx, ifname, global_priv, 0, NULL,NULL);
}static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,void *global_priv, int hostapd,const u8 *set_addr,const char *driver_params)
{struct wpa_driver_nl80211_data *drv;struct i802_bss *bss;if (global_priv == NULL)return NULL;drv = os_zalloc(sizeof(*drv));if (drv == NULL)return NULL;drv->global = global_priv;drv->ctx = ctx;drv->hostapd = !!hostapd;drv->eapol_sock = -1;/** There is no driver capability flag for this, so assume it is* supported and disable this on first attempt to use if the driver* rejects the command due to missing support.*/drv->set_rekey_offload = 1;drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);drv->if_indices = drv->default_if_indices;drv->if_indices_reason = drv->default_if_indices_reason;drv->first_bss = os_zalloc(sizeof(*drv->first_bss));if (!drv->first_bss) {os_free(drv);return NULL;}bss = drv->first_bss;bss->drv = drv;bss->ctx = ctx;os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));drv->monitor_ifidx = -1;drv->monitor_sock = -1;drv->eapol_tx_sock = -1;drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;if (nl80211_init_bss(bss))goto failed;if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params))goto failed;drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);if (drv->eapol_tx_sock < 0)goto failed;if (drv->data_tx_status) {int enabled = 1;if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,&enabled, sizeof(enabled)) < 0) {wpa_printf(MSG_DEBUG,"nl80211: wifi status sockopt failed\n");drv->data_tx_status = 0;if (!drv->use_monitor)drv->capa.flags &=~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;} else {eloop_register_read_sock(drv->eapol_tx_sock,wpa_driver_nl80211_handle_eapol_tx_status,drv, NULL);}}if (drv->global) {nl80211_check_global(drv->global);dl_list_add(&drv->global->interfaces, &drv->list);drv->in_interface_list = 1;}return bss;failed:wpa_driver_nl80211_deinit(bss);return NULL;
}

不是很看得懂了。、、

2.流程梳理

真正创建sta的地方HalDeviceManager

createStaIface - > createIface - > createIfaceIfPossible - > executeChipReconfiguration - > configureChip

wifi_chip.cpp

WifiStatus WifiChip::configureChipInternal(/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,ChipModeId mode_id) {if (!isValidModeId(mode_id)) {return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);}if (mode_id == current_mode_id_) {LOG(DEBUG) << "Already in the specified mode " << mode_id;return createWifiStatus(WifiStatusCode::SUCCESS);}WifiStatus status = handleChipConfiguration(lock, mode_id);if (status.code != WifiStatusCode::SUCCESS) {for (const auto& callback : event_cb_handler_.getCallbacks()) {if (!callback->onChipReconfigureFailure(status).isOk()) {LOG(ERROR)<< "Failed to invoke onChipReconfigureFailure callback";}}return status;}for (const auto& callback : event_cb_handler_.getCallbacks()) {if (!callback->onChipReconfigured(mode_id).isOk()) {LOG(ERROR) << "Failed to invoke onChipReconfigured callback";}}current_mode_id_ = mode_id;LOG(INFO) << "Configured chip in mode " << mode_id;return status;
}WifiStatus WifiChip::handleChipConfiguration(/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,ChipModeId mode_id) {// If the chip is already configured in a different mode, stop// the legacy HAL and then start it after firmware mode change.if (isValidModeId(current_mode_id_)) {LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_<< " to mode " << mode_id;invalidateAndRemoveAllIfaces();legacy_hal::wifi_error legacy_status =legacy_hal_.lock()->stop(lock, []() {});if (legacy_status != legacy_hal::WIFI_SUCCESS) {LOG(ERROR) << "Failed to stop legacy HAL: "<< legacyErrorToString(legacy_status);return createWifiStatusFromLegacyError(legacy_status);}}// Firmware mode change not needed for V2 devices.bool success = true;if (mode_id == kV1StaChipModeId) {success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);} else if (mode_id == kV1ApChipModeId) {success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);}if (!success) {return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);}legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();if (legacy_status != legacy_hal::WIFI_SUCCESS) {LOG(ERROR) << "Failed to start legacy HAL: "<< legacyErrorToString(legacy_status);return createWifiStatusFromLegacyError(legacy_status);}// Every time the HAL is restarted, we need to register the// radio mode change callback.WifiStatus status = registerRadioModeChangeCallback();if (status.code != WifiStatusCode::SUCCESS) {// This probably is not a critical failure?LOG(ERROR) << "Failed to register radio mode change callback";}return createWifiStatus(WifiStatusCode::SUCCESS);
}

之后会调用到legacy_hal_的start方法

wifi_legacy_hal.cpp

wifi_error WifiLegacyHal::start() {// Ensure that we're starting in a good state.CHECK(global_func_table_.wifi_initialize && !global_handle_ &&iface_name_to_handle_.empty() && !awaiting_event_loop_termination_);if (is_started_) {LOG(DEBUG) << "Legacy HAL already started";return WIFI_SUCCESS;}LOG(DEBUG) << "Waiting for the driver ready";wifi_error status = global_func_table_.wifi_wait_for_driver_ready();if (status == WIFI_ERROR_TIMED_OUT) {LOG(ERROR) << "Timed out awaiting driver ready";return status;}LOG(DEBUG) << "Starting legacy HAL";if (!iface_tool_.SetWifiUpState(true)) {LOG(ERROR) << "Failed to set WiFi interface up";return WIFI_ERROR_UNKNOWN;}status = global_func_table_.wifi_initialize(&global_handle_);if (status != WIFI_SUCCESS || !global_handle_) {LOG(ERROR) << "Failed to retrieve global handle";return status;}std::thread(&WifiLegacyHal::runEventLoop, this).detach();status = retrieveIfaceHandles();if (status != WIFI_SUCCESS || iface_name_to_handle_.empty()) {LOG(ERROR) << "Failed to retrieve wlan interface handle";return status;}LOG(DEBUG) << "Legacy HAL start complete";is_started_ = true;return WIFI_SUCCESS;
}

frameworks/opt/net/wifi/libwifi_system_iface/interface_tool.cpp

bool InterfaceTool::SetUpState(const char* if_name, bool request_up) {base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));if (sock.get() < 0) {LOG(ERROR) << "Failed to open socket to set up/down state ("<< strerror(errno) << ")";return false;}struct ifreq ifr;if (!GetIfState(if_name, sock.get(), &ifr)) {return false;  // logging done internally}const bool currently_up = ifr.ifr_flags & IFF_UP;if (currently_up == request_up) {return true;}if (request_up) {ifr.ifr_flags |= IFF_UP;} else {ifr.ifr_flags &= ~IFF_UP;}if (TEMP_FAILURE_RETRY(ioctl(sock.get(), SIOCSIFFLAGS, &ifr)) != 0) {LOG(ERROR) << "Could not set interface flags for " << if_name<< " (" << strerror(errno) << ")";return false;}return true;
}bool InterfaceTool::SetWifiUpState(bool request_up) {return SetUpState(kWlan0InterfaceName, request_up);
}

这边看起来是通过ioctl下发命令将iface(默认wlan0)启动起来,这里原生代码写的不大好,既然能接收ifacename,为何不继续往下传呢。

3. 总结

legacy hal start的时候会将iface创建起来。

贴一下百度到的legacy hal是个啥

HAL_legacy:旧式的HAL是一个模块,采用 共享库形式,在编译时会调用到。由于采用function
call形式调用,因此可被多个进程使用,但会被mapping到多个进程空间中,造 成浪费,同时需要考虑代码能否安全重入的问题(thread safe)。
HAL:新式的HAL采用HAL module和HAL stub结合形式,HAL stub不是一个share library,编译时上层只拥有访问HAL stub的函数指针,并不需要HAL stub。上层通过HAL module提供的统一接口获取并操作HAL stub,so文件只会被mapping到一个进程,也不存在重复mapping和重入问题。

(一百五十一)Android P 真正创建sta iface的地方相关推荐

  1. Kubernetes详解(五十一)——Kubernetes用户创建

    今天继续给大家介绍Linux运维相关知识,本文主要内容是Kubernetes用户创建. 在上文Kubernetes详解(五十)--Kubernetes权限配置中,我们介绍了Kubernetes的con ...

  2. Android开发笔记(一百五十一)WebView与JavaScript交互的四种形式

    WebView如果作为简单的网页浏览器,对于一般的浏览行为来说,已经足够了.可做为企业开发者,你的App通常要嵌入自家公司的网页,如此一来,还得考虑App与Web之间的消息传递,这就涉及到App的原生 ...

  3. 67键键盘如何输出`和~符号(一百五十一)

    1.使用需求 因为67键键盘符合黄金分割,看上去特别舒服,但是在使用67键蓝牙键盘的时候,因为最上一排没有F1.F2...等,所以需要输出F1.F2需要借助Fn键 . 但是需要输出的特殊的" ...

  4. Kubernetes详解(五十三)——Kubernetes Role创建和Rolebinding

    今天继续给大家介绍Linux运维相关知识,本文主要内容是Kubernetes Role创建和Rolebinding. 一.Kubernetes Role创建 首先,我们先来创建一个Role.我们可以通 ...

  5. Gradle 2.0 用户指南翻译——第五十一章. 发布工件

    本文禁止w3cschool转载! 翻译项目请关注Github上的地址:https://github.com/msdx/gradledoc . 本文翻译所在分支:https://github.com/m ...

  6. OpenCV学习笔记(五十一)——imge stitching图像拼接stitching OpenCV学习笔记(五十二)——号外:OpenCV 2.4.1 又出来了。。。。。 OpenCV学习笔记(五

    OpenCV学习笔记(五十一)--imge stitching图像拼接stitching stitching是OpenCV2.4.0一个新模块,功能是实现图像拼接,所有的相关函数都被封装在Stitch ...

  7. 创建构建方法android,如何快速创建并发布一个 Android 库

    一. 前言 最近经常看到各种大神的库,发现用起来非常方便,自己研究了一下,来写个库发布一下,让自己写代码更加方便一点,自己封装了基本的开发工具类.也是搜集了各位大神的优秀代码总结的. 二.必要的准备工 ...

  8. Android 渗透测试学习手册 第五章 Android 取证

    第五章 Android 取证 作者:Aditya Gupta 译者:飞龙 协议:CC BY-NC-SA 4.0 5.1 取证类型 取证是使用不同的手动和自动方法从设备中提取和分析数据.它可以大致分为两 ...

  9. JavaScript学习(五十一)—实训题

    JavaScript学习(五十一)-实训题 实训1 定义一个长方形的构造函数(有参数,通过参数给属性赋值)属性:长.宽方法:面积.周长通过这个构造方法创建3个对象,计算面积和周长 实训2 定义创建等边 ...

  10. 频谱仪的更改ip_【正点原子FPGA连载】第五十一章 基于FFT IP核的音频频谱仪-摘自【正点原子】开拓者 FPGA 开发指南 (amobbs.com 阿莫电子论坛)...

    本帖最后由 正点原子 于 2020-10-24 15:19 编辑 203429z6c3os33t8albi33.png (66.36 KB) 2019-7-28 15:14 上传 第五十一章 基于FF ...

最新文章

  1. Win7环境下VS2010配置Cocos2d-x-2.1.4最新版本的开发环境(亲测)
  2. 体育场[带权并查集]
  3. mysql每秒57000_MySQL 性能:使用 MySQL 5.7 实现每秒 50 万查询
  4. Java程序员该如何学习才能成长为一名优秀的架构师
  5. python怎么在运行中查看执行状态,Python程序运行时查看对象状态怎样设计才能实现...
  6. linux下为php开启oci8扩展(ubuntu14亲测可用)
  7. Scrapy框架(持久化,去重,深度控制,cookie)
  8. img标签过滤加fs模块实现图片文件缓存
  9. (已更新)婚礼类小程序前端界面模板源码
  10. php jmail 乱码,Jmail发送邮件与带附件乱码解决办法分享
  11. 庆祝北大“如何制作MOOC”课程取得优秀成绩
  12. Vanilla JS——最轻快的JavaScript框架
  13. DEFCON GROUP 010上竟玩了这些好玩的东西!
  14. Cross_entropy和softmax
  15. android studio 遇到 app error launching怎么办?
  16. fatal remote does not appear to be a git repository
  17. mysql 查询不等于空的数据查询
  18. 大工18秋计算机1答案,大工18秋《专业英语(计算机英语)》在线作业1.docx
  19. python开发环境部署以及调试教程
  20. 【微软chatGPT版bing上线了,使用体验如何,符合你的需求吗?】

热门文章

  1. Delphi FireDAC SQLite “database is locked“ 解决办法
  2. matplotlib画图教程系列之-堆积柱状图
  3. 网易云课堂整站源码 THINKPHP二开仿网易云课堂
  4. luogu 2735 电网 皮克公式
  5. 快速由PCI迁移到PCIe
  6. 基于linux 的 PCI PCIe 总线分析总结
  7. 网络流量分类方法调研
  8. TTL电路与CMOS电路对比
  9. DKMS:Dynamic Kernel Module Support
  10. 2022年全球程序员薪资排行出炉:中国倒数第九,GO最赚钱