当前位置:   article > 正文

WiFi 连接过程_wifi连接流程csdn

wifi连接流程csdn

1. 在 WifiNative 类中 connectNetwork 被调用用于连接,其主要工作为停止当前扫描过程,删除 wpa_supplicant 中的网络配置信息,并将新的配置传送给 wpa_supplicant 保存,这会触发对已有配置网络的 disconnect 操作,最后触发 reconnect 操作到 wpa_supplicant:

  1. /**
  2. * Add the provided network configuration to wpa_supplicant and initiate connection to it.
  3. * This method does the following:
  4. * 1. Abort any ongoing scan to unblock the connection request.
  5. * 2. Remove any existing network in wpa_supplicant(This implicitly triggers disconnect).
  6. * 3. Add a new network to wpa_supplicant.
  7. * 4. Save the provided configuration to wpa_supplicant.
  8. * 5. Select the new network in wpa_supplicant.
  9. * 6. Triggers reconnect command to wpa_supplicant.
  10. *
  11. * @param ifaceName Name of the interface.
  12. * @param configuration WifiConfiguration parameters for the provided network.
  13. * @return {@code true} if it succeeds, {@code false} otherwise
  14. */
  15. public boolean connectToNetwork(@NonNull String ifaceName, WifiConfiguration configuration) {
  16. // Abort ongoing scan before connect() to unblock connection request.
  17. mWifiCondManager.abortScan(ifaceName);
  18. return mSupplicantStaIfaceHal.connectToNetwork(ifaceName, configuration);
  19. }

2. SupplicantStaIfaceHal 类中的 connectToNetwork 方法被调用:

  1. /**
  2. * Add the provided network configuration to wpa_supplicant and initiate connection to it.
  3. * This method does the following:
  4. * 1. If |config| is different to the current supplicant network, removes all supplicant
  5. * networks and saves |config|.
  6. * 2. Select the new network in wpa_supplicant.
  7. *
  8. * @param ifaceName Name of the interface.
  9. * @param config WifiConfiguration parameters for the provided network.
  10. * @return {@code true} if it succeeds, {@code false} otherwise
  11. */
  12. public boolean connectToNetwork(@NonNull String ifaceName, @NonNull WifiConfiguration config) {
  13. synchronized (mLock) {
  14. logd("connectToNetwork " + config.getKey());
  15. WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName);
  16. /* 如果新旧配置对应的网络是同一个 */
  17. if (WifiConfigurationUtil.isSameNetwork(config, currentConfig)) {
  18. String networkSelectionBSSID = config.getNetworkSelectionStatus()
  19. .getNetworkSelectionBSSID();
  20. String networkSelectionBSSIDCurrent =
  21. currentConfig.getNetworkSelectionStatus().getNetworkSelectionBSSID();
  22. if (Objects.equals(networkSelectionBSSID, networkSelectionBSSIDCurrent)) {
  23. logd("Network is already saved, will not trigger remove and add operation.");
  24. } else {
  25. logd("Network is already saved, but need to update BSSID.");
  26. if (!setCurrentNetworkBssid(
  27. ifaceName,
  28. config.getNetworkSelectionStatus().getNetworkSelectionBSSID())) {
  29. loge("Failed to set current network BSSID.");
  30. return false;
  31. }
  32. mCurrentNetworkLocalConfigs.put(ifaceName, new WifiConfiguration(config));
  33. }
  34. } else { /* 新旧配置对应的网络部是同一个,也有可能存在一个配置是 null */
  35. /* 删除 HashMap 中 ifaceName 对应的配置 */
  36. mCurrentNetworkRemoteHandles.remove(ifaceName);
  37. /* 删除 HashMap 中 ifaceName 对应的配置 */
  38. mCurrentNetworkLocalConfigs.remove(ifaceName);
  39. if (!removeAllNetworks(ifaceName)) {
  40. loge("Failed to remove existing networks");
  41. return false;
  42. }
  43. Pair<SupplicantStaNetworkHal, WifiConfiguration> pair =
  44. addNetworkAndSaveConfig(ifaceName, config);
  45. if (pair == null) {
  46. loge("Failed to add/save network configuration: " + config.getKey());
  47. return false;
  48. }
  49. mCurrentNetworkRemoteHandles.put(ifaceName, pair.first);
  50. mCurrentNetworkLocalConfigs.put(ifaceName, pair.second);
  51. }
  52. SupplicantStaNetworkHal networkHandle =
  53. checkSupplicantStaNetworkAndLogFailure(ifaceName, "connectToNetwork");
  54. if (networkHandle == null) {
  55. loge("No valid remote network handle for network configuration: "
  56. + config.getKey());
  57. return false;
  58. }
  59. PmkCacheStoreData pmkData = mPmkCacheEntries.get(config.networkId);
  60. if (pmkData != null
  61. && !WifiConfigurationUtil.isConfigForPskNetwork(config)
  62. && pmkData.expirationTimeInSec > mClock.getElapsedSinceBootMillis() / 1000) {
  63. logi("Set PMK cache for config id " + config.networkId);
  64. if (networkHandle.setPmkCache(pmkData.data)) {
  65. mWifiMetrics.setConnectionPmkCache(true);
  66. }
  67. }
  68. if (!networkHandle.select()) {
  69. loge("Failed to select network configuration: " + config.getKey());
  70. return false;
  71. }
  72. return true;
  73. }
  74. }

3. 假设一开始配置为空,新增加了一条配置,则会进入 else 操作,重点进行分析,首先来看 removeAllNetworks 接口的操作:

  1. /**
  2. * Remove all networks from supplicant
  3. *
  4. * @param ifaceName Name of the interface.
  5. */
  6. public boolean removeAllNetworks(@NonNull String ifaceName) {
  7. synchronized (mLock) {
  8. ArrayList<Integer> networks = listNetworks(ifaceName);
  9. if (networks == null) {
  10. Log.e(TAG, "removeAllNetworks failed, got null networks");
  11. return false;
  12. }
  13. for (int id : networks) {
  14. if (!removeNetwork(ifaceName, id)) {
  15. Log.e(TAG, "removeAllNetworks failed to remove network: " + id);
  16. return false;
  17. }
  18. }
  19. // Reset current network info. Probably not needed once we add support to remove/reset
  20. // current network on receiving disconnection event from supplicant (b/32898136).
  21. mCurrentNetworkRemoteHandles.remove(ifaceName);
  22. mCurrentNetworkLocalConfigs.remove(ifaceName);
  23. return true;
  24. }
  25. }

4. 进而来看 listNetworks,因为这里面我们会进入到底层 Hal 以及 wpa_supplicant 的操作过程:

  1. /**
  2. * @return a list of SupplicantNetworkID ints for all networks controlled by supplicant, returns
  3. * null if the call fails
  4. */
  5. private java.util.ArrayList<Integer> listNetworks(@NonNull String ifaceName) {
  6. synchronized (mLock) {
  7. final String methodStr = "listNetworks";
  8. ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
  9. if (iface == null) return null;
  10. Mutable<ArrayList<Integer>> networkIdList = new Mutable<>();
  11. try {
  12. iface.listNetworks((SupplicantStatus status, ArrayList<Integer> networkIds) -> {
  13. if (checkStatusAndLogFailure(status, methodStr)) {
  14. networkIdList.value = networkIds;
  15. }
  16. });
  17. } catch (RemoteException e) {
  18. handleRemoteException(e, methodStr);
  19. }
  20. return networkIdList.value;
  21. }
  22. }

① 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 操作:

  1. /**
  2. * Add a network configuration to wpa_supplicant.
  3. *
  4. * @param config Config corresponding to the network.
  5. * @return a Pair object including SupplicantStaNetworkHal and WifiConfiguration objects
  6. * for the current network.
  7. */
  8. private Pair<SupplicantStaNetworkHal, WifiConfiguration>
  9. addNetworkAndSaveConfig(@NonNull String ifaceName, WifiConfiguration config) {
  10. synchronized (mLock) {
  11. logi("addSupplicantStaNetwork via HIDL");
  12. if (config == null) {
  13. loge("Cannot add NULL network!");
  14. return null;
  15. }
  16. SupplicantStaNetworkHal network = addNetwork(ifaceName);
  17. if (network == null) {
  18. loge("Failed to add a network!");
  19. return null;
  20. }
  21. boolean saveSuccess = false;
  22. try {
  23. saveSuccess = network.saveWifiConfiguration(config);
  24. } catch (IllegalArgumentException e) {
  25. Log.e(TAG, "Exception while saving config params: " + config, e);
  26. }
  27. if (!saveSuccess) {
  28. loge("Failed to save variables for: " + config.getKey());
  29. if (!removeAllNetworks(ifaceName)) {
  30. loge("Failed to remove all networks on failure.");
  31. }
  32. return null;
  33. }
  34. return new Pair(network, new WifiConfiguration(config));
  35. }
  36. }

这里重点是 addNetwork 方法,从此开始由 Iface 类型转换到 Network 类型的操作上,需要返回的是 SupplicantStaNetworkHal 对象,该对象是新创建,包含了 ISupplicantStaNetwork 的 HIDL 客户端对象,Context 信息以及 WifiMonitor 信息,而 ISupplicantStaNetwork 对象是在进行 iface 的 addNetwork 中创建的:

  1. /* sta_iface.cpp,StaIface 类实现 */
  2. std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
  3. StaIface::addNetworkInternal()
  4. {
  5. android::sp<ISupplicantStaNetwork> network;
  6. struct wpa_supplicant *wpa_s = retrieveIfacePtr();
  7. struct wpa_ssid *ssid = wpa_supplicant_add_network(wpa_s);
  8. if (!ssid) {
  9. return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
  10. }
  11. HidlManager *hidl_manager = HidlManager::getInstance();
  12. if (!hidl_manager ||
  13. hidl_manager->getStaNetworkHidlObjectByIfnameAndNetworkId(
  14. wpa_s->ifname, ssid->id, &network)) {
  15. return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
  16. }
  17. return {{SupplicantStatusCode::SUCCESS, ""}, network};
  18. }

这里调用 wpa_supplicant_add_network 添加 network,并且通过 HidlManager 的 getStaNetworkHidlObjectByIfnameAndNetworkId 获取到对应的 network 信息返回;

10. network 对应 HIDL 服务端创建过程发生在 HidlManager::registerNetwork 方法中:

  1. /**
  2. * Register a network to hidl manager.
  3. *
  4. * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
  5. * the network is added.
  6. * @param ssid |wpa_ssid| struct corresponding to the network being added.
  7. *
  8. * @return 0 on success, 1 on failure.
  9. */
  10. int HidlManager::registerNetwork(
  11. struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
  12. {
  13. if (!wpa_s || !ssid)
  14. return 1;
  15. // Generate the key to be used to lookup the network.
  16. const std::string network_key =
  17. getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
  18. if (isP2pIface(wpa_s)) {
  19. if (addHidlObjectToMap<P2pNetwork>(
  20. network_key,
  21. new P2pNetwork(wpa_s->global, wpa_s->ifname, ssid->id),
  22. p2p_network_object_map_)) {
  23. wpa_printf(
  24. MSG_ERROR,
  25. "Failed to register P2P network with HIDL "
  26. "control: %d",
  27. ssid->id);
  28. return 1;
  29. }
  30. p2p_network_callbacks_map_[network_key] =
  31. std::vector<android::sp<ISupplicantP2pNetworkCallback>>();
  32. // Invoke the |onNetworkAdded| method on all registered
  33. // callbacks.
  34. callWithEachP2pIfaceCallback(
  35. wpa_s->ifname,
  36. std::bind(
  37. &ISupplicantP2pIfaceCallback::onNetworkAdded,
  38. std::placeholders::_1, ssid->id));
  39. } else {
  40. if (addHidlObjectToMap<StaNetwork>(
  41. network_key,
  42. new StaNetwork(wpa_s->global, wpa_s->ifname, ssid->id),
  43. sta_network_object_map_)) {
  44. wpa_printf(
  45. MSG_ERROR,
  46. "Failed to register STA network with HIDL "
  47. "control: %d",
  48. ssid->id);
  49. return 1;
  50. }
  51. sta_network_callbacks_map_[network_key] =
  52. std::vector<android::sp<ISupplicantStaNetworkCallback>>();
  53. // Invoke the |onNetworkAdded| method on all registered
  54. // callbacks.
  55. callWithEachStaIfaceCallback(
  56. wpa_s->ifname,
  57. std::bind(
  58. &ISupplicantStaIfaceCallback::onNetworkAdded,
  59. std::placeholders::_1, ssid->id));
  60. }
  61. return 0;
  62. }

对应的 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 方法:

  1. SupplicantStatus StaNetwork::selectInternal()
  2. {
  3. struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
  4. if (wpa_ssid->disabled == 2) {
  5. return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
  6. }
  7. struct wpa_supplicant *wpa_s = retrieveIfacePtr();
  8. wpa_s->scan_min_time.sec = 0;
  9. wpa_s->scan_min_time.usec = 0;
  10. wpa_supplicant_select_network(wpa_s, wpa_ssid);
  11. return {SupplicantStatusCode::SUCCESS, ""};
  12. }

可以看到其内部实际上调用的是 wpa_supplicant_select_network 通用控制接口,实际功能为 “Attempt association with a network”,尝试与对应的网络进行协商;

15. wpa_supplicant 连接过程会发生相应的状态变化,对应的变化过程需要通知给上层,而通知的回调则是在 SupplicantStaIfaceHal 类的 setupStaIface 接口中创建 SupplicantStaIface 的过程中注册的:

  1. /**
  2. * Helper function to set up StaIface with different HAL version.
  3. *
  4. * This helper function would try newer version recursively.
  5. * Once the latest version is found, it would register the callback
  6. * of the latest version and skip unnecessary older HAL init flow.
  7. *
  8. * New version callback will be extended from the older one, as a result,
  9. * older callback is always created regardless of the latest version.
  10. *
  11. * Uprev steps:
  12. * 1. add new helper function trySetupStaIfaceV1_Y.
  13. * 2. call newly added function in trySetupStaIfaceV1_X (X should be Y-1).
  14. */
  15. private ISupplicantStaIface setupStaIface(@NonNull String ifaceName,
  16. @NonNull ISupplicantIface ifaceHwBinder) throws RemoteException {
  17. /* Prepare base type for later cast. */
  18. ISupplicantStaIface iface = getStaIfaceMockable(ifaceHwBinder);
  19. /* try newer version first. */
  20. if (trySetupStaIfaceV1_1(ifaceName, iface)) {
  21. logd("Newer HAL is found, skip V1_0 remaining init flow.");
  22. return iface;
  23. }
  24. SupplicantStaIfaceHalCallback callback = new SupplicantStaIfaceHalCallback(ifaceName);
  25. if (!registerCallback(iface, callback)) {
  26. throw new RemoteException("Init StaIface V1_0 failed.");
  27. }
  28. /* keep this in a store to avoid recycling by garbage collector. */
  29. mISupplicantStaIfaceCallbacks.put(ifaceName, callback);
  30. return iface;
  31. }

对应的网络相关的事件都会通过该回调进行反馈,hardware/interfaces/wifi/supplicant/1.0/ISupplicantStaNetwork.hal 中关于注册接口的说明如下:

  1. /**
  2. * Register for callbacks from this network.
  3. *
  4. * These callbacks are invoked for events that are specific to this network.
  5. * Registration of multiple callback objects is supported. These objects must
  6. * be automatically deleted when the corresponding client process is dead or
  7. * if this network is removed.
  8. *
  9. * @param callback An instance of the |ISupplicantStaNetworkCallback| HIDL
  10. * interface object.
  11. * @return status Status of the operation.
  12. * Possible status codes:
  13. * |SupplicantStatusCode.SUCCESS|,
  14. * |SupplicantStatusCode.FAILURE_UNKNOWN|,
  15. * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
  16. */
  17. registerCallback(ISupplicantStaNetworkCallback callback)
  18. generates (SupplicantStatus status);

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/317099
推荐阅读
相关标签
  

闽ICP备14008679号