当前位置:   article > 正文

Android Q WiFi Enable_failed to start supplicant

failed to start supplicant

wifi 启动流程梳理

 

--->App

 设置界面启动wifi

1、wifisettings:设置中wifi主界面对应的代码

2、WifiEnabler:设置中负责wifi开关打开和关闭事件处理的类

--->wifisettings.java 中的onstart函数

                                    

此函数创建了WifiEnabler类,实现了wifi的开关功能,

 

---creatWifiEnabler(),创建WifEnable这个类同时使用了SwitchBarController这个类,目的是为了监听开关的状态,

当开关打开时会调用相应的函数处理 

                              

 

---SwitchBarController这个类,需要关注两个函数startListening和onSwitchChanged,一个是启动SwitchBar的监听,一个监听到有变化之后的调用

                                       

                                    

当检测到开关打开后,会调用onSwitchToggled函数处理

 

--->WifiEnabler.java中的wifiEnabler函数

                           

---setupSwitchController()的作用就是把控制变量设置为ture启动SwitchBar的监听。

---onSwitchToggled(boolean isChecked),打开wifi开关,此函数为处理入口

                        

SwitchToggled中会调用WifiManager.setWifiEnabled方法。看到这里其实发现应用层打开和关闭WiFi就是调用了WifiManager的setWifiEabled(boolean)接口

----------------------------------------------------------------------APP层总结------------------------------------------------------------------------------------

   wifi的app层作用:创建wifienabler类,监控wifi开关。 监控到wifi开关状态改变,调用framework的wifimanager处理

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

--->AIDL

app和framework之间的通信是通过aidl机制,wifiservice和wifimanager之间就是才采用这样的方式

                     

                         WiFi相关的class

 IWifiManager, IWifiManager.Stub, IWifiManager.Stub.Proxy都由IWifiManger.aidl生成

WifiManager:系统为app提供的接口。

Context.getSystemService(Context.WIFI_SERVICE)返回的实际对象类型是IWifiManager.Stub.Proxy,这也就是应用层的对象。

IWifiManager.Stub.Proxy的实例:app端的代理,将WifiManager的方法的参数序列到parcel,经Binder发送给system_server进程

 

--->Framework

--->WifiServiceImpl中的setWifiEnabled方法。

    应用层的wifimanager.stub.proxy对象通过aidl将方法的参数序列发送到wifiservice进程,并调用相应的方法。

    WifiServiceImpl中实现WifiService的方法,

    setWifiEnabled方法中,打印log->进行wifi打开动作是否允许的判断->向WifiController发消息:CMD_WIFI_TOGGLED.

  1. "key log setWifiEnabled"
  2. Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
  3. + ", uid=" + Binder.getCallingUid() + ", package=" + packageName);
  4. ...
  5. mWifiController.sendMessage(CMD_WIFI_TOGGLED);

 

 --->状态机处理消息:CMD_WIFI_TOGGLED

      wifisevice处理之后就把任务交给了wifi的状态机进行处理 

--->WIFIEnable第一个状态机----------WifiControlle

    1、在初始化设置为StaDisabledState状态

     2、Enable流程中wifiservice会调用此状态机发送CMD_WIFI_TOGGLED消息\

    3、在StaDisabledState处理此消息状态机进入DeviceActiveState

   4、在DeviceActiveState的enter函数中调用mWifiStateMachinePrime.enterClientMode()

 

--->WIFIEnable第二个状态机--------ModeStateMachin

  1、初始设置为WiFiDisableState状态

  2、在WifiController中由DeviceActiveState的enter函数调用enterClientMode()调用到此状态机

  3、在WiFiDisableState状态处理CMD_STAR_CLIENT_MODE消息进入ClientModeActiveState

  4、ClientModeActiveState的enter函数工作

    --->ClientModeManager.start

    -->updateBatteryStatsWifiState

 

--->WIFIEnable第三个状态机--------ClientModeStateMachine

  1、初始状态IdleState

  2、由ModeStateMachine状态机的ClientModeActiveState的enter调用

  3、IdleState状态处理CMD_START消息,

     wifinative.setupInterForClienMode进行驱动装载、使能supplicant、wifimonitor、创建网口等

--->wifinative中的setupInterForClienMode方法

   wifi enable 过程wifi状态机的控制到这里基本完成了他的使命,接下里WifiNative中的setupInterForClienMode将调用其他的类来完成接下来的工作

  1. public String setupInterfaceForClientMode(boolean lowPrioritySta,
  2. @NonNull InterfaceCallback interfaceCallback) {
  3. synchronized (mLock) {
  4. if (!startHal()) {
  5. Log.e(TAG, "Failed to start Hal");
  6. mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
  7. return null;
  8. }
  9. if (!startSupplicant()) {
  10. Log.e(TAG, "Failed to start supplicant");
  11. mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
  12. return null;
  13. }
  14. Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA);
  15. if (iface == null) {
  16. Log.e(TAG, "Failed to allocate new STA iface");
  17. return null;
  18. }
  19. iface.externalListener = interfaceCallback;
  20. iface.name = createStaIface(iface, lowPrioritySta);
  21. if (TextUtils.isEmpty(iface.name)) {
  22. Log.e(TAG, "Failed to create STA iface in vendor HAL");
  23. mIfaceMgr.removeIface(iface.id);
  24. mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
  25. return null;
  26. }
  27. if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) {
  28. Log.e(TAG, "Failed to setup iface in wificond on " + iface);
  29. teardownInterface(iface.name);
  30. mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
  31. return null;
  32. }
  33. if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {
  34. Log.e(TAG, "Failed to setup iface in supplicant on " + iface);
  35. teardownInterface(iface.name);
  36. mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
  37. return null;
  38. }
  39. iface.networkObserver = new NetworkObserverInternal(iface.id);
  40. if (!registerNetworkObserver(iface.networkObserver)) {
  41. Log.e(TAG, "Failed to register network observer on " + iface);
  42. teardownInterface(iface.name);
  43. return null;
  44. }
  45. mWifiMonitor.startMonitoring(iface.name);
  46. // Just to avoid any race conditions with interface state change callbacks,
  47. // update the interface state before we exit.
  48. onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
  49. initializeNwParamsForClientInterface(iface.name);
  50. Log.i(TAG, "Successfully setup " + iface);
  51. return iface.name;
  52. }
  53. }

关键性的操作:
启动Hal:startHal()
启动supplicant:startSupplicant()
创建网口:setupInterfaceForClientMode()
启动WifiMonitor:WifiMonitor.startMonitoring()

WifiMonitor.startMonitoring():这一步主要是在WifiMonitor中建立与wpa_supplicant通信的socket通道、创建一个线程接收底层事件并分发处理。这里会创建两个socket通道与wpa_s通信,一个用于下发指令,另一个用于接收事件。成功后WifiMonitor会向WifiStateMachine发送一个代表socket通信建立成功的消息:SUP_CONNECTION_EVENT;收到这个消息就表示Wifi已经启动成功了

--->startHal()将启动hal层装载驱动

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

 

--->wifivendorHal.java

在此文件中的startVendorHal方法中没有没有其他的实质性的操作,也是直接调用的HalDeviceaManager的start方法

  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. }

--->HalDeviceaManager.java

startHal从wifinative到目前这个文件的start方法之前,都没有什么实质性操作,真正有操作的地方从HalDeviceaManager中的start方法开始。

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

关键点看Iwifi,到这里wif enable的工作framework 已经处理完了,接下来使用hidl通信使打开流程从java走到c++也就是到HAl层

startwifi的功能是状态驱动一直到成功,如果超过规定的时间没有完成,就会返回错误

---------------------------------------------------------------framework总结-----------------------------------------------------------------------------------

framework最关键的点就是wifi状态机了,状态机记录了wifi的各种状态,当wifi的状态改变时,我们就利用状态机来管理,最后一个状态机的改变往往会做真正的工作,向下层传递工作内容。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

--->HIDL

--->hardware/interfaces/wifi/1.0/IWifi.hal

此文件主要是向framework层提供一些接口

同目录下的Android.bp会在编译中产生一些头文件和源文件

对于C++的Iwifi.hal接口实现的地方,我们需要找到继承了Iwifi.hal里面包含的包和Iwifi.h文件

根据代码查找wifi.cpp是接口实现的文件

--->wifi.cpp start()方法

  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. "key log Wifi HAL started "
  2. WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
  3. if (wifi_status.code == WifiStatusCode::SUCCESS) {
  4. // Create the chip instance once the HAL is started.
  5. chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,
  6. feature_flags_);
  7. run_state_ = RunState::STARTED;
  8. for (const auto& callback : event_cb_handler_.getCallbacks()) {
  9. if (!callback->onStart().isOk()) {
  10. LOG(ERROR) << "Failed to invoke onStart callback";
  11. };
  12. }
  13. LOG(INFO) << "Wifi HAL started";

startInternal方法主要就是调用 initializeModeControllerAndLegacyHal()进行下一部处理,并对处结构进行反馈。如果驱动已经成功加载,在此答应关键log " wifi HAL started"

initializeModeControllerAndLegacyHal()方法把任务交给了HIDL层C++文件中的wifi_mode_controller.cpp

  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只有一个工作就是调用HAL层装载驱动

  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. }

--------------------------------------------------------------HIDL总结-------------------------------------------------------------------------------------------

HIDL是为了给framework通信而存在的,C++文件都是上层接口的实现,wifi_mode_controller.cpp会调用更底层的HAl层来实现,可能他就是边缘文件,专门来调用HAl而存在的,因为在这个文件中处除了调用HAL层就没有做其他的事情。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------

--->HAL 

HAL主要包含3个文件driver_tool .cpp    hal_tool.cpp     wifi_hal_commom.cppHIdL中实现的接口,最终也要调到HAL层,像装载驱动,需要用到驱动工具driver_tool.cpp的LoadDriver,

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

此方法的实际调用的wifi_hal_commom.cpp中的wifi_load_driver

  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. }

 几经周折终于到了真正装载驱动得代码,在insmod中根据我们定义的驱动实际的路径,执行装载驱动的动作。

---------------------------------------------------------------HAL层总结-----------------------------------------------------------------------------------------

Wifi Enable 工作到了HAl层首先要经过driver_tool .cpp中的LoadDriver方法,但是真正的装载是在wifi_hal_commom.cpp中。可能后者才是真的工作执行的位置,前者是用来工作分类的,所有的驱动类的工作都在driver_tool .cpp文件中,便于更好的管理。  

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

以上便是装载wifi驱动的过程,接下来start supplicat -> createStaIface ->  startMonitoring 类似装载驱动的流程,完成以上工作wifi 就算完成了打开工作,会广播wifi_state_change_action 这一类的消息,这样系统就知道wiif已经打开,可以进行扫描了

 

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

闽ICP备14008679号