wifi 启动流程梳理

--->App

 设置界面启动wifi

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

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

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

                                    

android 启用wifi 命令 android控制wifi开关_状态机

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

 

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

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

                              

android 启用wifi 命令 android控制wifi开关_android 启用wifi 命令_02

 

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

                                       

android 启用wifi 命令 android控制wifi开关_android 启用wifi 命令_03

                                    

android 启用wifi 命令 android控制wifi开关_状态机_04

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

 

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

                           

android 启用wifi 命令 android控制wifi开关_应用层_05

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

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

                        

android 启用wifi 命令 android控制wifi开关_java_06

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

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

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

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

 

--->AIDL

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

                     

                         

android 启用wifi 命令 android控制wifi开关_状态机_07

 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.

"key log setWifiEnabled"

 Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
                    + ", uid=" + Binder.getCallingUid() + ", package=" + packageName);

...
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将调用其他的类来完成接下来的工作

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

关键性的操作:
启动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层装载驱动

"WifiNative code 使用WiFiVendor 方法"
/** 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;
    }
}

 

--->wifivendorHal.java

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

/**
* 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;
    }
}

--->HalDeviceaManager.java

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

/**
* 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;
        }
    }
}

关键点看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()方法

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

在此方法中也调用startInternal这个方法

"key log Wifi HAL started "

 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";

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

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

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);
}

 

--->wifi_mode_controller.cpp 中的initialize只有一个工作就是调用HAL层装载驱动

bool WifiModeController::initialize() {
      if (!driver_tool_->LoadDriver()) {
         LOG(ERROR) << "Failed to load WiFi driver";
         return false;
      }
    return true;
}

--------------------------------------------------------------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,

bool DriverTool::LoadDriver() {
  return ::wifi_load_driver() == 0;
}

此方法的实际调用的wifi_hal_commom.cpp中的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;
}

 几经周折终于到了真正装载驱动得代码,在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已经打开,可以进行扫描了