美文网首页蓝牙和WIFI
Wifi笔记 | 启动流程 Native层

Wifi笔记 | 启动流程 Native层

作者: 力卉编程 | 来源:发表于2020-01-02 10:47 被阅读0次

    一、Manager层调用到WifiNative

    看一些关键性的操作:

    • 启动Hal:startHal()
    • 启动supplicant:startSupplicant()
    • 加载驱动(loadDriver):setupInterfaceForClientMode()
    • 启动WifiMonitor:WifiMonitor.startMonitoring()

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

    //frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
    /**
    * Setup an interface for Client mode operations.
    *
    * * This method configures an interface in STA mode in all the native daemons
    * (wificond, wpa_supplicant & vendor HAL).
    *
    * @param lowPrioritySta The requested STA has a low request priority (lower probability of
    *                       getting created, higher probability of getting destroyed).
    * @param interfaceCallback Associated callback for notifying status changes for the iface.
    * @return Returns the name of the allocated interface, will be null on failure.
    */
    public String setupInterfaceForClientMode(boolean lowPrioritySta,
    @NonNull InterfaceCallback interfaceCallback) {
        synchronized (mLock) {
            if (!startHal()) {
                Log.e(TAG, "Failed to start Hal");
                mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
                return null;
            }
            if (!startSupplicant()) {
                Log.e(TAG, "Failed to start supplicant");
                mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
                return null;
            }
            Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA);
            if (iface == null) {
                Log.e(TAG, "Failed to allocate new STA iface");
                return null;
            }
            iface.externalListener = interfaceCallback;
            iface.name = createStaIface(iface, lowPrioritySta);
            if (TextUtils.isEmpty(iface.name)) {
                Log.e(TAG, "Failed to create STA iface in vendor HAL");
                mIfaceMgr.removeIface(iface.id);
                mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
                return null;
            }
            if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) {
                Log.e(TAG, "Failed to setup iface in wificond on " + iface);
                teardownInterface(iface.name);
                mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
                return null;
            }
            if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {
                Log.e(TAG, "Failed to setup iface in supplicant on " + iface);
                teardownInterface(iface.name);
                mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
                return null;
            }
            iface.networkObserver = new NetworkObserverInternal(iface.id);
            if (!registerNetworkObserver(iface.networkObserver)) {
                Log.e(TAG, "Failed to register network observer on " + iface);
                teardownInterface(iface.name);
                return null;
            }
            mWifiMonitor.startMonitoring(iface.name);
            // Just to avoid any race conditions with interface state change callbacks,
            // update the interface state before we exit.
            onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
            initializeNwParamsForClientInterface(iface.name);
            Log.i(TAG, "Successfully setup " + iface);
            return iface.name;
        }
    }
    

    二、Native层

    2.1 startHal()
    /** Helper method invoked to start supplicant if there were no ifaces */
    private boolean startHal() {
        synchronized (mLock) {
            if (!mIfaceMgr.hasAnyIface()) {
                if (mWifiVendorHal.isVendorHalSupported()) {
                    if (!mWifiVendorHal.startVendorHal()) {
                        Log.e(TAG, "Failed to start vendor HAL");
                        return false;
                    }
                } else {
                    Log.i(TAG, "Vendor Hal not supported, ignoring start.");
                }
            }
            return true;
        }
    }
    
    2.2 mWifiVendorHal.startVendorHal()
    //frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiVendorHal.java
    
    /**
    * Bring up the HIDL Vendor HAL.
    * @return true on success, false otherwise.
    */
    public boolean startVendorHal() {
        synchronized (sLock) {
            if (!mHalDeviceManager.start()) {
                mLog.err("Failed to start vendor HAL").flush();
                return false;
            }
            mLog.info("Vendor Hal started successfully").flush();
            return true;
        }
    }
    
    2.3 mHalDeviceaManager.start()
    //frameworks/opt/net/wifi/service/java/com/android/server/wifi/HalDeviceManager.java
    /**
    * Attempts to start Wi-Fi (using HIDL). Returns the success (true) or failure (false) or
    * the start operation. Will also dispatch any registered ManagerStatusCallback.onStart() on
    * success.
    *
    * Note: direct call to HIDL.
    */
    public boolean start() {
        return startWifi();
    }
    private boolean startWifi() {
        if (VDBG) Log.d(TAG, "startWifi");
     
        synchronized (mLock) {
            try {
                if (mWifi == null) {
                    Log.w(TAG, "startWifi called but mWifi is null!?");
                    return false;
                } else {
                    int triedCount = 0;
                    while (triedCount <= START_HAL_RETRY_TIMES) {
                        WifiStatus status = mWifi.start();
                        if (status.code == WifiStatusCode.SUCCESS) {
                            initIWifiChipDebugListeners();
                            managerStatusListenerDispatch();
                            if (triedCount != 0) {
                                Log.d(TAG, "start IWifi succeeded after trying "
                                         + triedCount + " times");
                            }
                            return true;
                        } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {
                            // Should retry. Hal might still be stopping.
                            Log.e(TAG, "Cannot start IWifi: " + statusString(status)
                                    + ", Retrying...");
                            try {
                                Thread.sleep(START_HAL_RETRY_INTERVAL_MS);
                            } catch (InterruptedException ignore) {
                                // no-op
                            }
                            triedCount++;
                        } else {
                            // Should not retry on other failures.
                            Log.e(TAG, "Cannot start IWifi: " + statusString(status));
                            return false;
                        }
                    }
                    Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times");
                    return false;
                }
            } catch (RemoteException e) {
                Log.e(TAG, "startWifi exception: " + e);
                return false;
            }
        }
    }
    
    2.4 WifiStatus status = mWifi.start()

    mWifi是IWifi的服务端。至此我们开始进入HIDL。

    /**
    * Wrapper function to access the HIDL services. Created to be mockable in unit-tests.
    */
    protected IWifi getWifiServiceMockable() {
        try {
            return IWifi.getService();
        } catch (RemoteException e) {
            Log.e(TAG, "Exception getting IWifi service: " + e);
            return null;
        }
    }
    

    三、 HIDL 接口调用

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

    系统编译的时候会自动产生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

    //hardware/interfaces/wifi/1.0/IWifi.hal
    /**
    * Perform any setup that is required to make use of the module. If the module
    * is already started then this must be a noop.
    * Must trigger |IWifiEventCallback.onStart| on success.
    *
    * @return status WifiStatus of the operation.
    *         Possible status codes:
    *         |WifiStatusCode.SUCCESS|,
    *         |WifiStatusCode.NOT_AVAILABLE|,
    *         |WifiStatusCode.UNKNOWN|
    */
    @entry
    @callflow(next={"registerEventCallback", "start", "stop", "getChip"})
    start() generates (WifiStatus status);
    

    IWifi.java的getService方法

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

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

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

    四、硬件WIFI调用

    按照IWifi.java的代码接下来的调用路径应该在hardware/interfaces/wifi/1.0/default/,但没有发现这个路径下有wifi.cpp这个文件,hardware/interfaces/wifi/1.2/default/倒是有wifi.cpp,这个我也不清楚为什么,估计是HIDL的继承关系导致。

    4.1 入口 Wifi::start
    //hardware/interfaces/wifi/1.2/default/wifi.cpp
    Return<void> Wifi::start(start_cb hidl_status_cb) {
        return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
                &Wifi::startInternal, hidl_status_cb);
    }
    WifiStatus Wifi::startInternal() {
        if (run_state_ == RunState::STARTED) {
            return createWifiStatus(WifiStatusCode::SUCCESS);
        } else if (run_state_ == RunState::STOPPING) {
            return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
                                    "HAL is stopping");
        }
        WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
        if (wifi_status.code == WifiStatusCode::SUCCESS) {
            // Create the chip instance once the HAL is started.
            chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,
                                feature_flags_);
            run_state_ = RunState::STARTED;
            for (const auto& callback : event_cb_handler_.getCallbacks()) {
                if (!callback->onStart().isOk()) {
                    LOG(ERROR) << "Failed to invoke onStart callback";
                };
            }
            LOG(INFO) << "Wifi HAL started";
        } else {
            for (const auto& callback : event_cb_handler_.getCallbacks()) {
                if (!callback->onFailure(wifi_status).isOk()) {
                    LOG(ERROR) << "Failed to invoke onFailure callback";
                }
            }
            LOG(ERROR) << "Wifi HAL start failed";
        }
        return wifi_status;
    }
    
    4.2 初始化 initializeModeControllerAndLegacyHal()
    WifiStatus Wifi::initializeModeControllerAndLegacyHal() {
        if (!mode_controller_->initialize()) {
            LOG(ERROR) << "Failed to initialize firmware mode controller";
            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
        }
        legacy_hal::wifi_error legacy_status = legacy_hal_->initialize();
        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
            LOG(ERROR) << "Failed to initialize legacy HAL: "
                       << legacyErrorToString(legacy_status);
            return createWifiStatusFromLegacyError(legacy_status);
        }
        return createWifiStatus(WifiStatusCode::SUCCESS);
    }
    
    4.3 mode_controller_->initialize()
    //hardware/interfaces/wifi/1.2/default/wifi_mode_controller.cpp
    bool WifiModeController::initialize() {
        if (!driver_tool_->LoadDriver()) {
            LOG(ERROR) << "Failed to load WiFi driver";
            return false;
        }
        return true;
    }
    
    4.4 driver_tool_->LoadDriver()

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

    //frameworks/opt/net/wifi/libwifi_hal/driver_tool.cpp
    bool DriverTool::LoadDriver() {
      return ::wifi_load_driver() == 0;
    }
    
    4.4 wifi_load_driver()
    int wifi_load_driver() {
    #ifdef WIFI_DRIVER_MODULE_PATH
      if (is_wifi_driver_loaded()) {
        return 0;
      }
     
      if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1;
    #endif
     
    #ifdef WIFI_DRIVER_STATE_CTRL_PARAM
      if (is_wifi_driver_loaded()) {
        return 0;
      }
     
      if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0) return -1;
    #endif
      property_set(DRIVER_PROP_NAME, "ok");
      return 0;
    }
    
    4.5 结果

    调用驱动,通知上层:

    • insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG)
    • wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0)
    • property_set(DRIVER_PROP_NAME, "ok");
    • 结束

    五、 wpa_supplicant

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

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

    六、 Linux Kernel

    Wifi的内核驱动程序
    kernel/driver/net/wireless/
    vendor/gcom/opensource/wlan/

    完~~~

    文 | 力卉编程

    相关文章

      网友评论

        本文标题:Wifi笔记 | 启动流程 Native层

        本文链接:https://www.haomeiwen.com/subject/fyvnoctx.html