分享

Wifi模块

 共同成长888 2020-08-31

 一 前言

   在上一篇分析了wifi启动的流程,从Android应用层一直分析到了Java框架层,这次我们接着往下走流程。如果没有看上一篇的建议先回头看看   Wifi模块—源码分析Wifi启动1(Android P)这样能更好地认知和把握wifi的启动过程。

 

二 图示调用流程

    这个调用流程图也是基于上一篇的流程图进一步完善的得到的。

 

三 代码具体流程

1 应用层

直接看 Wifi模块—源码分析Wifi启动1(Android P)

 

2 java 框架层

       前面部分直接看 Wifi模块—源码分析Wifi启动1(Android P),这一层也不标注明确的节点数值,因为这一层的前面调用流程部分并未全部加到这里。所以直接去看前面一篇会更清晰。

我们直接从WifiNative.java这个类开始看。

 frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java

  1. /**
  2. * Setup an interface for Client mode operations.
  3. *
  4. * * This method configures an interface in STA mode in all the native daemons
  5. * (wificond, wpa_supplicant & vendor HAL).
  6. *
  7. * @param lowPrioritySta The requested STA has a low request priority (lower probability of
  8. * getting created, higher probability of getting destroyed).
  9. * @param interfaceCallback Associated callback for notifying status changes for the iface.
  10. * @return Returns the name of the allocated interface, will be null on failure.
  11. */
  12. public String setupInterfaceForClientMode(boolean lowPrioritySta,
  13. @NonNull InterfaceCallback interfaceCallback) {
  14. synchronized (mLock) {
  15. if (!startHal()) {
  16. Log.e(TAG, "Failed to start Hal");
  17. mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
  18. return null;
  19. }
  20. if (!startSupplicant()) {
  21. Log.e(TAG, "Failed to start supplicant");
  22. mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
  23. return null;
  24. }
  25. Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA);
  26. if (iface == null) {
  27. Log.e(TAG, "Failed to allocate new STA iface");
  28. return null;
  29. }
  30. iface.externalListener = interfaceCallback;
  31. iface.name = createStaIface(iface, lowPrioritySta);
  32. if (TextUtils.isEmpty(iface.name)) {
  33. Log.e(TAG, "Failed to create STA iface in vendor HAL");
  34. mIfaceMgr.removeIface(iface.id);
  35. mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
  36. return null;
  37. }
  38. if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) {
  39. Log.e(TAG, "Failed to setup iface in wificond on " + iface);
  40. teardownInterface(iface.name);
  41. mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
  42. return null;
  43. }
  44. if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {
  45. Log.e(TAG, "Failed to setup iface in supplicant on " + iface);
  46. teardownInterface(iface.name);
  47. mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
  48. return null;
  49. }
  50. iface.networkObserver = new NetworkObserverInternal(iface.id);
  51. if (!registerNetworkObserver(iface.networkObserver)) {
  52. Log.e(TAG, "Failed to register network observer on " + iface);
  53. teardownInterface(iface.name);
  54. return null;
  55. }
  56. mWifiMonitor.startMonitoring(iface.name);
  57. // Just to avoid any race conditions with interface state change callbacks,
  58. // update the interface state before we exit.
  59. onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
  60. initializeNwParamsForClientInterface(iface.name);
  61. Log.i(TAG, "Successfully setup " + iface);
  62. return iface.name;
  63. }
  64. }

看一些关键性的操作:

                         启动Hal:startHal()

                         启动supplicant:startSupplicant()

                         加载驱动(loadDriver):setupInterfaceForClientMode()

                         启动WifiMonitor:WifiMonitor.startMonitoring()

   这里我们就选择  启动Hal:startHal() 这条线走下去。

  1. /** Helper method invoked to start supplicant if there were no ifaces */
  2. private boolean startHal() {
  3. synchronized (mLock) {
  4. if (!mIfaceMgr.hasAnyIface()) {
  5. if (mWifiVendorHal.isVendorHalSupported()) {
  6. if (!mWifiVendorHal.startVendorHal()) {
  7. Log.e(TAG, "Failed to start vendor HAL");
  8. return false;
  9. }
  10. } else {
  11. Log.i(TAG, "Vendor Hal not supported, ignoring start.");
  12. }
  13. }
  14. return true;
  15. }
  16. }

看mWifiVendorHal.startVendorHal()。

 

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiVendorHal.java

  1. /**
  2. * Bring up the HIDL Vendor HAL.
  3. * @return true on success, false otherwise.
  4. */
  5. public boolean startVendorHal() {
  6. synchronized (sLock) {
  7. if (!mHalDeviceManager.start()) {
  8. mLog.err("Failed to start vendor HAL").flush();
  9. return false;
  10. }
  11. mLog.info("Vendor Hal started successfully").flush();
  12. return true;
  13. }
  14. }

看mHalDeviceaManager.start()。

 

frameworks/opt/net/wifi/service/java/com/android/server/wifi/HalDeviceManager.java

  1. /**
  2. * Attempts to start Wi-Fi (using HIDL). Returns the success (true) or failure (false) or
  3. * the start operation. Will also dispatch any registered ManagerStatusCallback.onStart() on
  4. * success.
  5. *
  6. * Note: direct call to HIDL.
  7. */
  8. public boolean start() {
  9. return startWifi();
  10. }

继续看startWifi()。

  1. private boolean startWifi() {
  2. if (VDBG) Log.d(TAG, "startWifi");
  3. synchronized (mLock) {
  4. try {
  5. if (mWifi == null) {
  6. Log.w(TAG, "startWifi called but mWifi is null!?");
  7. return false;
  8. } else {
  9. int triedCount = 0;
  10. while (triedCount <= START_HAL_RETRY_TIMES) {
  11. WifiStatus status = mWifi.start();
  12. if (status.code == WifiStatusCode.SUCCESS) {
  13. initIWifiChipDebugListeners();
  14. managerStatusListenerDispatch();
  15. if (triedCount != 0) {
  16. Log.d(TAG, "start IWifi succeeded after trying "
  17. + triedCount + " times");
  18. }
  19. return true;
  20. } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {
  21. // Should retry. Hal might still be stopping.
  22. Log.e(TAG, "Cannot start IWifi: " + statusString(status)
  23. + ", Retrying...");
  24. try {
  25. Thread.sleep(START_HAL_RETRY_INTERVAL_MS);
  26. } catch (InterruptedException ignore) {
  27. // no-op
  28. }
  29. triedCount++;
  30. } else {
  31. // Should not retry on other failures.
  32. Log.e(TAG, "Cannot start IWifi: " + statusString(status));
  33. return false;
  34. }
  35. }
  36. Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times");
  37. return false;
  38. }
  39. } catch (RemoteException e) {
  40. Log.e(TAG, "startWifi exception: " + e);
  41. return false;
  42. }
  43. }
  44. }

主要看WifiStatus status = mWifi.start(),先看下mWifi是什么。

  1. /**
  2. * Wrapper function to access the HIDL services. Created to be mockable in unit-tests.
  3. */
  4. protected IWifi getWifiServiceMockable() {
  5. try {
  6. return IWifi.getService();
  7. } catch (RemoteException e) {
  8. Log.e(TAG, "Exception getting IWifi service: " + e);
  9. return null;
  10. }
  11. }

这里返回的是IWifi的服务端。至此我们开始进入HIDL。

 

3 HIDL

      HIDL 读作 hide-l,Wifi到Andoid O之后所以Android P也一样不再使用jni,而是使用HIDL,Hardware Interface Define Language。

3.1 hardware/interfaces/wifi/1.0/IWifi.hal

  1. /**
  2. * Perform any setup that is required to make use of the module. If the module
  3. * is already started then this must be a noop.
  4. * Must trigger |IWifiEventCallback.onStart| on success.
  5. *
  6. * @return status WifiStatus of the operation.
  7. * Possible status codes:
  8. * |WifiStatusCode.SUCCESS|,
  9. * |WifiStatusCode.NOT_AVAILABLE|,
  10. * |WifiStatusCode.UNKNOWN|
  11. */
  12. @entry
  13. @callflow(next={"registerEventCallback", "start", "stop", "getChip"})
  14. start() generates (WifiStatus status);

系统编译的时候会自动产生IWifi.java文件。

out/soong/.intermediates/hardware/interfaces/wifi/1.0/android.hardware.wifi_V1.0-java_gen_java/gen/android/hardware/wifi/V1_0/IWifi.java

IWifi.java的getService方法

  1. public static IWifi getService(String serviceName) throws android.os.RemoteException {
  2. return IWifi.asInterface(android.os.HwBinder.getService("android.hardware.wifi@1.0::IWifi",serviceName));
  3. }

 再看一下 IWifi.java的asInterface方法。

IWifi.asInterface(android.os.HwBinder.getService("android.hardware.wifi@1.0::IWifi",serviceName));

从而我们就可以知道IWifi对应的服务端了。

 

3.2 hardware/interfaces/wifi/1.2/default/wifi.cpp

按照IWifi.java的代码接下来的调用路径应该在hardware/interfaces/wifi/1.0/default/,但没有发现这个路径下有wifi.cpp这个文件,hardware/interfaces/wifi/1.2/default/倒是有wifi.cpp,这个我也不清楚为什么。那就先按这个调用流程走下去吧。

  1. Return<void> Wifi::start(start_cb hidl_status_cb) {
  2. return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
  3. &Wifi::startInternal, hidl_status_cb);
  4. }

  看startInternal()。

  1. WifiStatus Wifi::startInternal() {
  2. if (run_state_ == RunState::STARTED) {
  3. return createWifiStatus(WifiStatusCode::SUCCESS);
  4. } else if (run_state_ == RunState::STOPPING) {
  5. return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
  6. "HAL is stopping");
  7. }
  8. WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
  9. if (wifi_status.code == WifiStatusCode::SUCCESS) {
  10. // Create the chip instance once the HAL is started.
  11. chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,
  12. feature_flags_);
  13. run_state_ = RunState::STARTED;
  14. for (const auto& callback : event_cb_handler_.getCallbacks()) {
  15. if (!callback->onStart().isOk()) {
  16. LOG(ERROR) << "Failed to invoke onStart callback";
  17. };
  18. }
  19. LOG(INFO) << "Wifi HAL started";
  20. } else {
  21. for (const auto& callback : event_cb_handler_.getCallbacks()) {
  22. if (!callback->onFailure(wifi_status).isOk()) {
  23. LOG(ERROR) << "Failed to invoke onFailure callback";
  24. }
  25. }
  26. LOG(ERROR) << "Wifi HAL start failed";
  27. }
  28. return wifi_status;
  29. }
  1. WifiStatus Wifi::initializeModeControllerAndLegacyHal() {
  2. if (!mode_controller_->initialize()) {
  3. LOG(ERROR) << "Failed to initialize firmware mode controller";
  4. return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
  5. }
  6. legacy_hal::wifi_error legacy_status = legacy_hal_->initialize();
  7. if (legacy_status != legacy_hal::WIFI_SUCCESS) {
  8. LOG(ERROR) << "Failed to initialize legacy HAL: "
  9. << legacyErrorToString(legacy_status);
  10. return createWifiStatusFromLegacyError(legacy_status);
  11. }
  12. return createWifiStatus(WifiStatusCode::SUCCESS);
  13. }

 接着看wifi_mode_controller.cpp得initialize()方法。

 

 3.3 hardware/interfaces/wifi/1.2/default/wifi_mode_controller.cpp

  1. bool WifiModeController::initialize() {
  2. if (!driver_tool_->LoadDriver()) {
  3. LOG(ERROR) << "Failed to load WiFi driver";
  4. return false;
  5. }
  6. return true;
  7. }

再继续看driver_tool.cpp这里开始走到WPA适配层了。

 

4 WPA适配层(硬件抽象层 HAL)

       HAL 可定义一个标准接口以供硬件供应商实现,这可让 Android 忽略较低级别的驱动程序实现。借助 HAL,可以顺利实现相关功能,而不会影响或更改更高级别的系统。HAL 实现会被封装成模块,并由 Android 系统适时地加载。

      wpa_supplicant适配层是通用的wpa_supplicant的封装,在Android中作为WiFi部分的硬件抽象层来使用。wpa_supplicant适配层主要用于与wpa_supplicant守护进程的通信,以提供给Android框架使用,它实现了加载、控制和消息监控等功能。

4.1frameworks/opt/net/wifi/libwifi_hal/driver_tool.cpp

  1. bool DriverTool::LoadDriver() {
  2. return ::wifi_load_driver() == 0;
  3. }

 

4.2 frameworks/opt/net/wifi/libwifi_hal/wifi_hal_common.cpp

  1. int wifi_load_driver() {
  2. #ifdef WIFI_DRIVER_MODULE_PATH
  3. if (is_wifi_driver_loaded()) {
  4. return 0;
  5. }
  6. if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1;
  7. #endif
  8. #ifdef WIFI_DRIVER_STATE_CTRL_PARAM
  9. if (is_wifi_driver_loaded()) {
  10. return 0;
  11. }
  12. if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0) return -1;
  13. #endif
  14. property_set(DRIVER_PROP_NAME, "ok");
  15. return 0;
  16. }

看is_wifi_driver_loaded()。

  1. int is_wifi_driver_loaded() {
  2. char driver_status[PROPERTY_VALUE_MAX];
  3. #ifdef WIFI_DRIVER_MODULE_PATH
  4. FILE *proc;
  5. char line[sizeof(DRIVER_MODULE_TAG) + 10];
  6. #endif
  7. if (!property_get(DRIVER_PROP_NAME, driver_status, NULL) ||
  8. strcmp(driver_status, "ok") != 0) {
  9. return 0; /* driver not loaded */
  10. }
  11. #ifdef WIFI_DRIVER_MODULE_PATH
  12. /*
  13. * If the property says the driver is loaded, check to
  14. * make sure that the property setting isn't just left
  15. * over from a previous manual shutdown or a runtime
  16. * crash.
  17. */
  18. if ((proc = fopen(MODULE_FILE, "r")) == NULL) {
  19. PLOG(WARNING) << "Could not open " << MODULE_FILE;
  20. property_set(DRIVER_PROP_NAME, "unloaded");
  21. return 0;
  22. }
  23. while ((fgets(line, sizeof(line), proc)) != NULL) {
  24. if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) {
  25. fclose(proc);
  26. return 1;
  27. }
  28. }
  29. fclose(proc);
  30. property_set(DRIVER_PROP_NAME, "unloaded");
  31. return 0;
  32. #else
  33. return 1;
  34. #endif
  35. }

 

5 wpa_supplicant

       wpa_supplicant是一个开源项目,已经被移植到Linux,Windows以及很多嵌入式系统上。它是WPA的应用层认证客户端,负责完成认证相关的登录、加密等工作。wpa_supplicant的源代码目录为:

             /external/wpa_supplicant_8/

        wpa_supplicant是一个独立运行的守护进程,其核心是一个消息循环,在消息循环中处理WPA状态机、控制命令、驱动事件、配置信息等。wpa_supplicant有很多控制接口,也提供命令行和通行界面的控制模式:而Android与wpa_supplicant的通信通过Socket完成

 

6 Linux Kernel

Wifi的内核驱动程序

     kernel/driver/net/wireless/

     vendor/gcom/opensource/wlan/

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多