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之间就是才采用这样的方式
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已经打开,可以进行扫描了