赞
踩
1. 在 WifiNative 类中 connectNetwork 被调用用于连接,其主要工作为停止当前扫描过程,删除 wpa_supplicant 中的网络配置信息,并将新的配置传送给 wpa_supplicant 保存,这会触发对已有配置网络的 disconnect 操作,最后触发 reconnect 操作到 wpa_supplicant:
- /**
- * Add the provided network configuration to wpa_supplicant and initiate connection to it.
- * This method does the following:
- * 1. Abort any ongoing scan to unblock the connection request.
- * 2. Remove any existing network in wpa_supplicant(This implicitly triggers disconnect).
- * 3. Add a new network to wpa_supplicant.
- * 4. Save the provided configuration to wpa_supplicant.
- * 5. Select the new network in wpa_supplicant.
- * 6. Triggers reconnect command to wpa_supplicant.
- *
- * @param ifaceName Name of the interface.
- * @param configuration WifiConfiguration parameters for the provided network.
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- public boolean connectToNetwork(@NonNull String ifaceName, WifiConfiguration configuration) {
- // Abort ongoing scan before connect() to unblock connection request.
- mWifiCondManager.abortScan(ifaceName);
- return mSupplicantStaIfaceHal.connectToNetwork(ifaceName, configuration);
- }
2. SupplicantStaIfaceHal 类中的 connectToNetwork 方法被调用:
- /**
- * Add the provided network configuration to wpa_supplicant and initiate connection to it.
- * This method does the following:
- * 1. If |config| is different to the current supplicant network, removes all supplicant
- * networks and saves |config|.
- * 2. Select the new network in wpa_supplicant.
- *
- * @param ifaceName Name of the interface.
- * @param config WifiConfiguration parameters for the provided network.
- * @return {@code true} if it succeeds, {@code false} otherwise
- */
- public boolean connectToNetwork(@NonNull String ifaceName, @NonNull WifiConfiguration config) {
- synchronized (mLock) {
- logd("connectToNetwork " + config.getKey());
- WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName);
- /* 如果新旧配置对应的网络是同一个 */
- if (WifiConfigurationUtil.isSameNetwork(config, currentConfig)) {
- String networkSelectionBSSID = config.getNetworkSelectionStatus()
- .getNetworkSelectionBSSID();
- String networkSelectionBSSIDCurrent =
- currentConfig.getNetworkSelectionStatus().getNetworkSelectionBSSID();
- if (Objects.equals(networkSelectionBSSID, networkSelectionBSSIDCurrent)) {
- logd("Network is already saved, will not trigger remove and add operation.");
- } else {
- logd("Network is already saved, but need to update BSSID.");
- if (!setCurrentNetworkBssid(
- ifaceName,
- config.getNetworkSelectionStatus().getNetworkSelectionBSSID())) {
- loge("Failed to set current network BSSID.");
- return false;
- }
- mCurrentNetworkLocalConfigs.put(ifaceName, new WifiConfiguration(config));
- }
- } else { /* 新旧配置对应的网络部是同一个,也有可能存在一个配置是 null */
- /* 删除 HashMap 中 ifaceName 对应的配置 */
- mCurrentNetworkRemoteHandles.remove(ifaceName);
- /* 删除 HashMap 中 ifaceName 对应的配置 */
- mCurrentNetworkLocalConfigs.remove(ifaceName);
- if (!removeAllNetworks(ifaceName)) {
- loge("Failed to remove existing networks");
- return false;
- }
- Pair<SupplicantStaNetworkHal, WifiConfiguration> pair =
- addNetworkAndSaveConfig(ifaceName, config);
- if (pair == null) {
- loge("Failed to add/save network configuration: " + config.getKey());
- return false;
- }
- mCurrentNetworkRemoteHandles.put(ifaceName, pair.first);
- mCurrentNetworkLocalConfigs.put(ifaceName, pair.second);
- }
- SupplicantStaNetworkHal networkHandle =
- checkSupplicantStaNetworkAndLogFailure(ifaceName, "connectToNetwork");
- if (networkHandle == null) {
- loge("No valid remote network handle for network configuration: "
- + config.getKey());
- return false;
- }
-
- PmkCacheStoreData pmkData = mPmkCacheEntries.get(config.networkId);
- if (pmkData != null
- && !WifiConfigurationUtil.isConfigForPskNetwork(config)
- && pmkData.expirationTimeInSec > mClock.getElapsedSinceBootMillis() / 1000) {
- logi("Set PMK cache for config id " + config.networkId);
- if (networkHandle.setPmkCache(pmkData.data)) {
- mWifiMetrics.setConnectionPmkCache(true);
- }
- }
-
- if (!networkHandle.select()) {
- loge("Failed to select network configuration: " + config.getKey());
- return false;
- }
- return true;
- }
- }
3. 假设一开始配置为空,新增加了一条配置,则会进入 else 操作,重点进行分析,首先来看 removeAllNetworks 接口的操作:
- /**
- * Remove all networks from supplicant
- *
- * @param ifaceName Name of the interface.
- */
- public boolean removeAllNetworks(@NonNull String ifaceName) {
- synchronized (mLock) {
- ArrayList<Integer> networks = listNetworks(ifaceName);
- if (networks == null) {
- Log.e(TAG, "removeAllNetworks failed, got null networks");
- return false;
- }
- for (int id : networks) {
- if (!removeNetwork(ifaceName, id)) {
- Log.e(TAG, "removeAllNetworks failed to remove network: " + id);
- return false;
- }
- }
- // Reset current network info. Probably not needed once we add support to remove/reset
- // current network on receiving disconnection event from supplicant (b/32898136).
- mCurrentNetworkRemoteHandles.remove(ifaceName);
- mCurrentNetworkLocalConfigs.remove(ifaceName);
- return true;
- }
- }
4. 进而来看 listNetworks,因为这里面我们会进入到底层 Hal 以及 wpa_supplicant 的操作过程:
- /**
- * @return a list of SupplicantNetworkID ints for all networks controlled by supplicant, returns
- * null if the call fails
- */
- private java.util.ArrayList<Integer> listNetworks(@NonNull String ifaceName) {
- synchronized (mLock) {
- final String methodStr = "listNetworks";
- ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
- if (iface == null) return null;
- Mutable<ArrayList<Integer>> networkIdList = new Mutable<>();
- try {
- iface.listNetworks((SupplicantStatus status, ArrayList<Integer> networkIds) -> {
- if (checkStatusAndLogFailure(status, methodStr)) {
- networkIdList.value = networkIds;
- }
- });
- } catch (RemoteException e) {
- handleRemoteException(e, methodStr);
- }
- return networkIdList.value;
- }
- }
① ISupplicantStaIface 定义在 hardware/interfaces/wifi/supplicant/1.0/ISupplicantStaIface.hal 文件中,继承自 ISupplicantIface,定义在 hardware/interfaces/wifi/supplicant/1.0/ISupplicantIface.hal 文件中,在经过 HIDL 转化之后 Native 代码实现在 external/wpa_supplicant_8/wpa_supplicant/hidl/ 目录下,而 ISupplicantStaIface 对应的 cpp 实现是 StaIface 类,定义在 sta_iface.h,实现在 sta_iface.cpp
② 上面在 framework 层的实际处理过程会进入到 HIDL 转化后的服务层 Native 代码中,进而调用到 wpa_supplicant 中的接口展开响应的操作;
③ 通过 checkSupplicantStaIfaceAndLogFailure 获取到 iface 对象,调用其 listNetworks 进而进入到 Native 层的对应接口 StaIface::listNetworks,进一步调用 listNetworksInternal;
④ listNetworksInternal 等内部操作通过 struct wpa_supplicant 对象来获取相应的信息,这些信息即为底层 wpa_supplicant 内部维护的内容,每个 struct wpa_supplicant 对应一个 iface;
5. struct wpa_supplicant 的信息管理由 struct wpa_global 统一进行,而 struct wpa_global 是在 wpa_supplicant 初始化的时候由 wpa_supplicant_init() 进行初始化的,而 wpa_supplicant_init 则是直接在 main 函数中被调用,它完成了如下操作:
① wpa_supplicant_init 初始化之后进行 wpas_notify_supplicant_initialized 以告知所有可能的控制途径 wpa_global 已经初始化完成;
② 如果定义了 CONFIG_HIDL 则 wpas_notify_supplicant_initialized 会调用 wpas_hidl_init 初始化其类型为 struct wpas_hidl_priv 的 hidl 对象;
③ wpas_hidl_init 分配对应的对象并采用 wpa_global 进行其初始化,而这里面非常重要的一步是通过 HidlManager 的 registerHidlService 方法来注册 wpa_supplicant 对应的 HIDL 服务,在这里创建了 Supplicant 类对象,以初始化后的 wpa_global 类型的 global 为参数;
④ 可以看到在 wpa_supplicant 的管理过程中如前面需要获取网络配置对应的 struct wpa_supplicat 对象,调用了 wpa_supplicant_get_iface,都是需要以 struct wpa_global 为参数进行的
6. StaIface 类对象的创建和管理由 Supplicant 进行,创建过程中会将 struct wpa_global 对象作为参数传递,从而如上面我们通过 StaIface 的 listNetworks 方法可以直接调用 wpa_supplicant 内部的公共控制接口并将 struct wpa_global 对象作为参数直接传入;
7. 同样这里查询和操作的对应接口都是在 Supplicant 类中进行创建和管理的,位于 hidl 中的 supplicant.{h,cpp} 进行了定义和实现,如 addInterface 方法,然后调用了 addInterfaceInternal 内部方法,进而调用了 wpa_supplicant 的公共管理接口 wpa_supplicant_add_iface;
8. 返回前面主流程来,在 SupplicantStaIfaceHal 的方法 connectToNetwork 中继续执行 removeAllNetworks,将获取到的 list 进行遍历,依次对其进行 removeNetwork 操作,实际上还是调用了 StaIface 的 removeNetwork 方法进入 wpa_supplicant 进行操作;
9. 删除接口之后开始进入 addNetworkAndSaveConfig 操作:
- /**
- * Add a network configuration to wpa_supplicant.
- *
- * @param config Config corresponding to the network.
- * @return a Pair object including SupplicantStaNetworkHal and WifiConfiguration objects
- * for the current network.
- */
- private Pair<SupplicantStaNetworkHal, WifiConfiguration>
- addNetworkAndSaveConfig(@NonNull String ifaceName, WifiConfiguration config) {
- synchronized (mLock) {
- logi("addSupplicantStaNetwork via HIDL");
- if (config == null) {
- loge("Cannot add NULL network!");
- return null;
- }
- SupplicantStaNetworkHal network = addNetwork(ifaceName);
- if (network == null) {
- loge("Failed to add a network!");
- return null;
- }
- boolean saveSuccess = false;
- try {
- saveSuccess = network.saveWifiConfiguration(config);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Exception while saving config params: " + config, e);
- }
- if (!saveSuccess) {
- loge("Failed to save variables for: " + config.getKey());
- if (!removeAllNetworks(ifaceName)) {
- loge("Failed to remove all networks on failure.");
- }
- return null;
- }
- return new Pair(network, new WifiConfiguration(config));
- }
- }
这里重点是 addNetwork 方法,从此开始由 Iface 类型转换到 Network 类型的操作上,需要返回的是 SupplicantStaNetworkHal 对象,该对象是新创建,包含了 ISupplicantStaNetwork 的 HIDL 客户端对象,Context 信息以及 WifiMonitor 信息,而 ISupplicantStaNetwork 对象是在进行 iface 的 addNetwork 中创建的:
- /* sta_iface.cpp,StaIface 类实现 */
- std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
- StaIface::addNetworkInternal()
- {
- android::sp<ISupplicantStaNetwork> network;
- struct wpa_supplicant *wpa_s = retrieveIfacePtr();
- struct wpa_ssid *ssid = wpa_supplicant_add_network(wpa_s);
- if (!ssid) {
- return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
- }
- HidlManager *hidl_manager = HidlManager::getInstance();
- if (!hidl_manager ||
- hidl_manager->getStaNetworkHidlObjectByIfnameAndNetworkId(
- wpa_s->ifname, ssid->id, &network)) {
- return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
- }
- return {{SupplicantStatusCode::SUCCESS, ""}, network};
- }
这里调用 wpa_supplicant_add_network 添加 network,并且通过 HidlManager 的 getStaNetworkHidlObjectByIfnameAndNetworkId 获取到对应的 network 信息返回;
10. network 对应 HIDL 服务端创建过程发生在 HidlManager::registerNetwork 方法中:
- /**
- * Register a network to hidl manager.
- *
- * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
- * the network is added.
- * @param ssid |wpa_ssid| struct corresponding to the network being added.
- *
- * @return 0 on success, 1 on failure.
- */
- int HidlManager::registerNetwork(
- struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
- {
- if (!wpa_s || !ssid)
- return 1;
-
- // Generate the key to be used to lookup the network.
- const std::string network_key =
- getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
-
- if (isP2pIface(wpa_s)) {
- if (addHidlObjectToMap<P2pNetwork>(
- network_key,
- new P2pNetwork(wpa_s->global, wpa_s->ifname, ssid->id),
- p2p_network_object_map_)) {
- wpa_printf(
- MSG_ERROR,
- "Failed to register P2P network with HIDL "
- "control: %d",
- ssid->id);
- return 1;
- }
- p2p_network_callbacks_map_[network_key] =
- std::vector<android::sp<ISupplicantP2pNetworkCallback>>();
- // Invoke the |onNetworkAdded| method on all registered
- // callbacks.
- callWithEachP2pIfaceCallback(
- wpa_s->ifname,
- std::bind(
- &ISupplicantP2pIfaceCallback::onNetworkAdded,
- std::placeholders::_1, ssid->id));
- } else {
- if (addHidlObjectToMap<StaNetwork>(
- network_key,
- new StaNetwork(wpa_s->global, wpa_s->ifname, ssid->id),
- sta_network_object_map_)) {
- wpa_printf(
- MSG_ERROR,
- "Failed to register STA network with HIDL "
- "control: %d",
- ssid->id);
- return 1;
- }
- sta_network_callbacks_map_[network_key] =
- std::vector<android::sp<ISupplicantStaNetworkCallback>>();
- // Invoke the |onNetworkAdded| method on all registered
- // callbacks.
- callWithEachStaIfaceCallback(
- wpa_s->ifname,
- std::bind(
- &ISupplicantStaIfaceCallback::onNetworkAdded,
- std::placeholders::_1, ssid->id));
- }
- return 0;
- }
对应的 StaNetwork 对象呗创建,并且添加到 sta_network_object_map_ 中,而 StaNetwork 类定义和实现在 sta_network.{h,cpp} 中,registerNetwork 是在 wpas_hidl_register_network 中被调用,继而被 wpas_notify_network_added 调用,调用时机是在 wpa_supplicant_add_network 内部添加了对应的 network 之后通知给监听和管理者;从而又回归到前面在分析的 StaIface::addNetworkInternal 中;
11. 继续返回到 Framework 层,addNetwork 创建 SupplicantStaNetworkHal 后将其返回,紧接着通过其 saveWiFiConfiguration 方法进行配置的保存,这里其实是调用了 SupplicantStaNetworkHal 中的接口通过 HIDL 将对应的信息配置到 wpa_supplicant 中维护的对应的 network 中,比如 ssid 信息;
12. 最终创建信息 WifiConfiguration 信息并与 network 配对之后返回 Pair<SupplicantStaNetworkHal, WifiConfiguration> 对象,WiFiConfiguration 对象为根据传递进来的 config 进行初始化的;
13. 再回到 connectToNetwork 中,将返回的 Pair 中两个配置信息分别加入到对应的 HashMap 中(mCurrentNetworkRemoteHandles 和 mCurrentNetworkLocalConfigs),更新缓存信息;
14. 紧接着调用了 SupplicantStaNetworkHal 类的 select 方法进行网络连接,实际上又回到其内部的 SupplicantStaNetwork 类,调用其 select 方法,进而调用到 Native 层 StaNetwork 类的 select 方法,继续回到 sta_network.cpp 中的 selectInternel 方法:
- SupplicantStatus StaNetwork::selectInternal()
- {
- struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
- if (wpa_ssid->disabled == 2) {
- return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
- }
- struct wpa_supplicant *wpa_s = retrieveIfacePtr();
- wpa_s->scan_min_time.sec = 0;
- wpa_s->scan_min_time.usec = 0;
- wpa_supplicant_select_network(wpa_s, wpa_ssid);
- return {SupplicantStatusCode::SUCCESS, ""};
- }
可以看到其内部实际上调用的是 wpa_supplicant_select_network 通用控制接口,实际功能为 “Attempt association with a network”,尝试与对应的网络进行协商;
15. wpa_supplicant 连接过程会发生相应的状态变化,对应的变化过程需要通知给上层,而通知的回调则是在 SupplicantStaIfaceHal 类的 setupStaIface 接口中创建 SupplicantStaIface 的过程中注册的:
- /**
- * Helper function to set up StaIface with different HAL version.
- *
- * This helper function would try newer version recursively.
- * Once the latest version is found, it would register the callback
- * of the latest version and skip unnecessary older HAL init flow.
- *
- * New version callback will be extended from the older one, as a result,
- * older callback is always created regardless of the latest version.
- *
- * Uprev steps:
- * 1. add new helper function trySetupStaIfaceV1_Y.
- * 2. call newly added function in trySetupStaIfaceV1_X (X should be Y-1).
- */
- private ISupplicantStaIface setupStaIface(@NonNull String ifaceName,
- @NonNull ISupplicantIface ifaceHwBinder) throws RemoteException {
- /* Prepare base type for later cast. */
- ISupplicantStaIface iface = getStaIfaceMockable(ifaceHwBinder);
-
- /* try newer version first. */
- if (trySetupStaIfaceV1_1(ifaceName, iface)) {
- logd("Newer HAL is found, skip V1_0 remaining init flow.");
- return iface;
- }
-
- SupplicantStaIfaceHalCallback callback = new SupplicantStaIfaceHalCallback(ifaceName);
- if (!registerCallback(iface, callback)) {
- throw new RemoteException("Init StaIface V1_0 failed.");
- }
- /* keep this in a store to avoid recycling by garbage collector. */
- mISupplicantStaIfaceCallbacks.put(ifaceName, callback);
- return iface;
- }
对应的网络相关的事件都会通过该回调进行反馈,hardware/interfaces/wifi/supplicant/1.0/ISupplicantStaNetwork.hal 中关于注册接口的说明如下:
- /**
- * Register for callbacks from this network.
- *
- * These callbacks are invoked for events that are specific to this network.
- * Registration of multiple callback objects is supported. These objects must
- * be automatically deleted when the corresponding client process is dead or
- * if this network is removed.
- *
- * @param callback An instance of the |ISupplicantStaNetworkCallback| HIDL
- * interface object.
- * @return status Status of the operation.
- * Possible status codes:
- * |SupplicantStatusCode.SUCCESS|,
- * |SupplicantStatusCode.FAILURE_UNKNOWN|,
- * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
- */
- registerCallback(ISupplicantStaNetworkCallback callback)
- generates (SupplicantStatus status);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。