本文介绍Android S上WiFi的Enable流程
1. WiFi开启流程
1. Framework流程
WifiManager.setWifiEnabled(true) -> WifiServiceImpl.enable(pkgName, true) -> setWifiEnabledInternal(packageName, enable, callingUid, callingPid, isPrivileged)
-> mSettingsStore.handleWifiToggled(enable) -> Settings.Global.putInt(cr, Settings.Global.WIFI_ON, state) && mPersistWifiState = state 记下wifi状态
-> mActiveModeWarden.wifiToggled(new WorkSource(callingUid, packageName)) 这里不关心enable的值
接下来由ActiveModeWarden内部的WifiController处理CMD_WIFI_TOGGLED消息
在打开wifi的情况下,此时wifi是disabled,由DisabledState处理
-> handleStaToggleChangeInDisabledState((WorkSource) msg.obj) -> startPrimaryOrScanOnlyClientModeManager(requestorWs) 然后直接进入enabled状态
private boolean startPrimaryOrScanOnlyClientModeManager(WorkSource requestorWs) {
ActiveModeManager.ClientRole role = getRoleForPrimaryOrScanOnlyClientModeManager();
if (role == ROLE_CLIENT_PRIMARY) {
return startPrimaryClientModeManager(requestorWs);
} else if (role == ROLE_CLIENT_SCAN_ONLY) {
return startScanOnlyClientModeManager(requestorWs);
} else {
return false;
}
}
private boolean startPrimaryClientModeManager(WorkSource requestorWs) {
Log.d(TAG, "Starting primary ClientModeManager in connect mode");
ConcreteClientModeManager manager = mWifiInjector.makeClientModeManager(
new ClientListener(), requestorWs, ROLE_CLIENT_PRIMARY, mVerboseLoggingEnabled);
mClientModeManagers.add(manager);
mLastPrimaryClientModeManagerRequestorWs = requestorWs;
return true;
}
打开wifi,对应的role是ROLE_CLIENT_PRIMARY
,接下来调用startPrimaryClientModeManager()
.
该方法内部通过WifiInjector创建一个新的ConcreteClientModeManager
对象,注意我们将ROLE_CLIENT_PRIMARY
传给了ConcreteClientModeManager
ConcreteClientModeManager
的构造方法在初始化结束后,会直接给自己发送一条CMD_START
消息,由其内部的ClientModeStateMachine
状态机处理
CMD_START由初始状态 IdleState 处理
// packages/modules/Wifi/service/java/com/android/server/wifi/ConcreteClientModeManager.java
ConcreteClientModeManager.ClientModeStateMachine.IdleState.processMessage(Message message) {
switch (message.what) {
case CMD_START:
// 1
mClientInterfaceName = mWifiNative.setupInterfaceForClientInScanMode(
mWifiNativeInterfaceCallback, roleChangeInfo.requestorWs);
if (roleChangeInfo.role instanceof ClientConnectivityRole) {
// 2
sendMessage(CMD_SWITCH_TO_CONNECT_MODE, roleChangeInfo);
transitionTo(mStartedState);
} else {
mScanRoleChangeInfoToSetOnTransition = roleChangeInfo;
transitionTo(mScanOnlyModeState);
}
// ... ...
}
setupInterfaceForClientInScanMode
传入了一个mWifiNativeInterfaceCallback
用来来自native层的iface状态回调
private final InterfaceCallback mWifiNativeInterfaceCallback = new InterfaceCallback() {
@Override
public void onDestroyed(String ifaceName) {
if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) {
Log.d(getTag(), "STA iface " + ifaceName + " was destroyed, "
+ "stopping client mode");
// we must immediately clean up state in ClientModeImpl to unregister
// all client mode related objects
// Note: onDestroyed is only called from the main Wifi thread
if (mClientModeImpl == null) {
Log.w(getTag(), "Received mWifiNativeInterfaceCallback.onDestroyed "
+ "callback when no ClientModeImpl instance is active.");
} else {
mClientModeImpl.handleIfaceDestroyed();
}
sendMessage(CMD_INTERFACE_DESTROYED);
}
}
@Override
public void onUp(String ifaceName) {
if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) {
sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1);
}
}
@Override
public void onDown(String ifaceName) {
if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) {
sendMessage(CMD_INTERFACE_STATUS_CHANGED, 0);
}
}
};
接着根据role的不同,分别进入StartedState
或者ScanOnlyModeState
,进入StartedState
之后,又收到IdleState
发出的CMD_SWITCH_TO_CONNECT_MODE
消息
// packages/modules/Wifi/service/java/com/android/server/wifi/ConcreteClientModeManager.java
ConcreteClientModeManager.ClientModeStateMachine.StartedState.processMessage(Message message) {
switch (message.what) {
case CMD_SWITCH_TO_CONNECT_MODE: {
updateConnectModeState(roleChangeInfo.role,
WifiManager.WIFI_STATE_ENABLING,
WifiManager.WIFI_STATE_DISABLED);
// 1
mWifiNative.switchClientInterfaceToConnectivityMode(mClientInterfaceName, roleChangeInfo.requestorWs)
mConnectRoleChangeInfoToSetOnTransition = roleChangeInfo;
transitionTo(mConnectModeState);
}
// ... ...
}
switchClientInterfaceToConnectivityMode
成功后,进入ConnectModeState
,并按需创建mClientModeImpl
。
注意exit ConnectModeState的时候会销毁mClientModeImpl
// packages/modules/Wifi/service/java/com/android/server/wifi/ConcreteClientModeManager.java
ConcreteClientModeManager.ClientModeStateMachine.ConnectModeState.Enter() {
mClientModeImpl = mWifiInjector.makeClientModeImpl(
mClientInterfaceName, ConcreteClientModeManager.this,
mVerboseLoggingEnabled);
mClientModeImpl.setShouldReduceNetworkScore(mShouldReduceNetworkScore);
}
public void exit() {
mClientModeImpl.stop();
mClientModeImpl = null;
}
到这里,其实wifi已经启动成功并切换到了connectable状态,接下来其实主要是ClientModeImpl的主场了
以上分析,涉及到的3个状态机如下,后面我们会介绍以下这几个状态机
-
ActiveModeWarden.WifiController
记录上层的WiFi开关状态(DisabledState/EnabledState)
DisabledState -> EnabledState
-
ConcreteClientModeManager.ClientModeStateMachine
WiFi的设备状态(IdleState/StartedState/ScanOnlyModeState/ConnectModeState)
IdleState -> StartedState -> ConnectModeState
-
ClientModeImpl
管理wifi的连接状态
DisconnectedState
撇开Framework层各种状态的转换,实际上Enable WiFi的最终操作都是由WifiNative下面的两个方法完成
/**
* Setup an interface for client mode (for scan) operations.
*
* This method configures an interface in STA mode in the native daemons
* (wificond, vendor HAL).
*
* @param interfaceCallback Associated callback for notifying status changes for the iface.
* @param requestorWs Requestor worksource.
* @return Returns the name of the allocated interface, will be null on failure.
*/
public String setupInterfaceForClientInScanMode(
@NonNull InterfaceCallback interfaceCallback, @NonNull WorkSource requestorWs);
/**
* Switches an existing Client mode interface from scan mode
* {@link Iface#IFACE_TYPE_STA_FOR_SCAN} to connectivity mode
* {@link Iface#IFACE_TYPE_STA_FOR_CONNECTIVITY}.
*
* @param ifaceName Name of the interface.
* @param requestorWs Requestor worksource.
* @return true if the operation succeeded, false if there is an error or the iface is already
* in scan mode.
*/
public boolean switchClientInterfaceToConnectivityMode(@NonNull String ifaceName,
@NonNull WorkSource requestorWs);
用白话来讲,setupInterfaceForClientInScanMode() 方法负责加载驱动,vendor hal, wificon并配置interface
switchClientInterfaceToConnectivityMode() 方法负责启动supplicant
2. WiFiNative
接下来介绍上面涉及到WifiNative最主要的两个函数
2.1 setupInterfaceForClientInScanMode 初始化interface
先启动scanmode
主体代码如下(去掉一些错误处理)
// 1. 初始化驱动和vendor hal
startHal();
// 2. 初始化interface
Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA_FOR_SCAN);
iface.externalListener = interfaceCallback;
iface.name = createStaIface(iface, requestorWs);
// 3. 初始化wificond
mWifiCondManager.setupInterfaceForClientMode(iface.name, Runnable::run,
new NormalScanEventCallback(iface.name),
new PnoScanEventCallback(iface.name));
//4. 监听interface的down/up
iface.networkObserver = new NetworkObserverInternal(iface.id);
registerNetworkObserver(iface.networkObserver)
// 5. 启动supplicant监听(但是此时supplicant进程还未启动)
mWifiMonitor.startMonitoring(iface.name);
onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
mWifiVendorHal.enableLinkLayerStats(iface.name);
// 6. 获取芯片支持的wifi feature
iface.featureSet = getSupportedFeatureSetInternal(iface.name);
WifiNative -> WifiVendorHal -> HalDeviceManager
2.1.1 驱动和WiFi HAL初始化
先starthal()
WifiNative.startHal() -> WifiVendorHal.startVendorHal() -> HalDeviceManager.start() -> HalDeviceManager.startWifi()
startWifi()方法其实主要就两行代码
// 通过hal接口启动
WifiStatus status = mWifi.start();
// 获取chip info
WifiChipInfo[] wifiChipInfos = getAllChipInfo();
IWifi.Start()
hardware/interface/wifi1.6/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() {
// ... ...
WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
// ... ...
// Create the chip instance once the HAL is started.
android::hardware::wifi::V1_0::ChipId chipId = kPrimaryChipId;
for (auto& hal : legacy_hals_) {
chips_.push_back(
new WifiChip(chipId, chipId == kPrimaryChipId, hal, mode_controller_,
std::make_shared<iface_util::WifiIfaceUtil>(iface_tool_, hal),
feature_flags_, on_subsystem_restart_callback));
chipId++;
}
}
WifiStatus Wifi::initializeModeControllerAndLegacyHal() {
// ... ...
mode_controller_->initialize(); // 加载驱动 driver_tool_->LoadDriver()
legacy_hals_ = legacy_hal_factory_->getHals();
for (auto& hal : legacy_hals_) {
legacy_hal::wifi_error legacy_status = hal->initialize();
// ... ...
}
// ... ...
}
std::vector<std::shared_ptr<WifiLegacyHal>> WifiLegacyHalFactory::getHals() {
if (legacy_hals_.empty()) {
// 先从已链接的so库中初始化vendor hal的接口(函数指针赋值)
// 如果失败,证明是多wifi芯片的设备,需要从descriptor.xml初始化
if (!initVendorHalDescriptorFromLinked()) initVendorHalsDescriptorList();
for (auto& desc : descs_) {
std::shared_ptr<WifiLegacyHal> hal =
std::make_shared<WifiLegacyHal>(iface_tool_, desc.fn, desc.primary);
legacy_hals_.push_back(hal);
}
}
return legacy_hals_;
}
那其实主要就是下面几步
- 通过wifi_mode_controller加载驱动
- 初始化所有的HAL接口(legacy_hal_factory_->getHals())
- initVendorHalDescriptorFromLinked
- initVendorHalsDescriptorList
从Android S(12)开始,支持多个wifi芯片,HAL层也做了一些修改,WiFi HAL 1.5及后面的版本都支持多wifi hal,vendor为每一个芯片提供一个HAL so,并且使用一个xml文件描述他们。该修改来自于commit 2dddd79e1645ea7d2ec41991bd00d6bfe4170ec7
commit 2dddd79e1645ea7d2ec41991bd00d6bfe4170ec7
Author: Jimmy Chen <jimmycmchen@google.com>
Date: Mon Dec 23 17:50:39 2019 +0200
Wifi: support multiple WIFI chips
The WIFI HAL API has support for multiple WIFI chips(IWifiChip instances) however the implementation is hard-coded to support only a single WIFI chip. This change reworks the implementation so multiple WIFI chips will be supported.
Support for multiple chips is based on the concept that each chip is represented by its own vendor HAL library. The implementation will look for descriptor files for vendor HAL libraries under /vendor/etc/wifi/vendor_hals. It will parse descriptors, dynamically load vendor HAL libraries and create WifiLegacyHal and WifiChip objects for each loaded vendor HAL library.
One of the descriptors should be marked with "primary" flag. The implementation will create the first WifiChip object for this library. Typically it is the one providing the best WIFI functionality, which was previously used as the only WIFI chip.
Additional support is added inside WifiChip and WifiLegacyHal for getting available chip modes and concurrency combinations from the vendor HAL if available, and allowing the chip to override network interface name when creating interfaces.
The mechanism for getting chip capabilities is improved to allow getting chip-global capabilities, which are independent of any created interfaces.
For example, if the framework needs to start a SoftAP on the 60GHz band, it needs to find a chip which supports this band, but before creating any interface on the chip. The new mechanism allows this.
Bug: 146922967
Test: atest VtsHalWifiV1_0TargetTest VtsHalWifiNanV1_0TargetTest VtsHalWifiApV1_0TargetTest \
VtsHalWifiV1_1TargetTest \
VtsHalWifiV1_2TargetTest VtsHalWifiNanV1_2TargetTest \
VtsHalWifiV1_3TargetTest \
VtsHalWifiApV1_4TargetTest VtsHalWifiNanV1_4TargetTest VtsHalWifiRttV1_4TargetTest
Change-Id: Ibdff93ea56aff186d4b5361ac77f6f448a0dfd45
现在我们再回头看一下initVendorHalDescriptorFromLinked和initVendorHalsDescriptorList两个方法就很好理解了。
initVendorHalDescriptorFromLinked()方法在已经链接的库中查找init_wifi_vendor_hal_func_table方法,并使用它对descriptor进行初始化,其实最主要的是对函数指针初始化
bool WifiLegacyHalFactory::initVendorHalDescriptorFromLinked() {
wifi_hal_lib_desc desc;
if (!initLinkedHalFunctionTable(&desc.fn)) return false;
desc.primary = true;
desc.handle = NULL;
descs_.push_back(desc);
return true;
}
bool WifiLegacyHalFactory::initLinkedHalFunctionTable(wifi_hal_fn* hal_fn) {
init_wifi_vendor_hal_func_table_t initfn;
// 在已经链接的库中查找 init_wifi_vendor_hal_func_table 方法
initfn = (init_wifi_vendor_hal_func_table_t)dlsym(RTLD_DEFAULT,
"init_wifi_vendor_hal_func_table");
if (!initfn) {
LOG(INFO) << "no vendor HAL library linked, will try dynamic load";
return false;
}
// 先给 wifi_hal_fn 对象内部的所有函数指针赋一个空实现,否则会是null,后面上层调用会报错
if (!initHalFuncTableWithStubs(hal_fn)) {
LOG(ERROR) << "Can not initialize the basic function pointer table";
return false;
}
// 这里依赖于vendor提供的legacy_hal实现,一般只是初始化函数指针,可以参考
// http://aospxref.com/android-13.0.0_r3/xref/hardware/qcom/wlan/qcwcn/wifi_hal/wifi_hal.cpp?r=&mo=17295&fi=547#547
if (initfn(hal_fn) != WIFI_SUCCESS) {
LOG(ERROR) << "Can not initialize the vendor function pointer table";
return false;
}
return true;
}
库配置以及多chip的配置在libwifi-hal的Android.mk里,LIB_WIFI_HAL就是legacy wifi hal 的库,如果定义WIFI_MULTIPLE_VENDOR_HALS
那么LIB_WIFI_HAL为空,而是要通过descriptor.xml定义
# Pick a vendor provided HAL implementation library.
# ============================================================
ifeq ($(WIFI_MULTIPLE_VENDOR_HALS), true)
# vendor HALs are loaded dynamically and not linked here
LIB_WIFI_HAL :=
else
LIB_WIFI_HAL ?= libwifi-hal-fallback
VENDOR_LOCAL_SHARED_LIBRARIES :=
ifeq ($(BOARD_WLAN_DEVICE), bcmdhd)
LIB_WIFI_HAL := libwifi-hal-bcm
VENDOR_LOCAL_SHARED_LIBRARIES := libcrypto
ifneq ($(wildcard vendor/google/libraries/GoogleWifiConfigLib),)
VENDOR_LOCAL_SHARED_LIBRARIES += \
google_wifi_firmware_config_version_c_wrapper
endif
else ifeq ($(BOARD_WLAN_DEVICE), synadhd)
LIB_WIFI_HAL := libwifi-hal-syna
VENDOR_LOCAL_SHARED_LIBRARIES := libcrypto
ifneq ($(wildcard vendor/google/libraries/GoogleWifiConfigLib),)
VENDOR_LOCAL_SHARED_LIBRARIES += \
google_wifi_firmware_config_version_c_wrapper
endif
else ifeq ($(BOARD_WLAN_DEVICE), qcwcn)
LIB_WIFI_HAL := libwifi-hal-qcom
VENDOR_LOCAL_SHARED_LIBRARIES := libcld80211
VENDOR_LOCAL_SHARED_LIBRARIES += libcrypto
else ifeq ($(BOARD_WLAN_DEVICE), mrvl)
# this is commented because none of the nexus devices
# that sport Marvell's wifi have support for HAL
# LIB_WIFI_HAL := libwifi-hal-mrvl
else ifeq ($(BOARD_WLAN_DEVICE), MediaTek)
# support MTK WIFI HAL
LIB_WIFI_HAL := libwifi-hal-mt66xx
else ifeq ($(BOARD_WLAN_DEVICE), realtek)
# support Realtek WIFI HAL
LIB_WIFI_HAL := libwifi-hal-rtk
else ifeq ($(BOARD_WLAN_DEVICE), emulator)
LIB_WIFI_HAL := libwifi-hal-emu
else ifeq ($(BOARD_WLAN_DEVICE), slsi)
LIB_WIFI_HAL := libwifi-hal-slsi
endif
endif
# The WiFi HAL that you should be linking.
# ============================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libwifi-hal
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
LOCAL_LICENSE_CONDITIONS := notice
LOCAL_PROPRIETARY_MODULE := true
LOCAL_CFLAGS := $(wifi_hal_cflags)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDE_DIRS := \
$(LOCAL_PATH)/include
LOCAL_EXPORT_HEADER_LIBRARY_HEADERS := libhardware_legacy_headers
LOCAL_HEADER_LIBRARIES := libhardware_legacy_headers
LOCAL_SHARED_LIBRARIES := \
libbase \
libcutils \
liblog \
libnl \
libutils \
$(VENDOR_LOCAL_SHARED_LIBRARIES)
LOCAL_SRC_FILES := \
driver_tool.cpp \
hal_tool.cpp
LOCAL_WHOLE_STATIC_LIBRARIES := $(LIB_WIFI_HAL) libwifi-hal-common
include $(BUILD_SHARED_LIBRARY)
我们以libwifi-hal-qcom
为例,其init_wifi_vendor_hal_func_table()
方法如下,只是为函数指针赋值
// hardware/qcom/wlan/qcwcn/wifi_hal/wifi_hal.cpp
/*initialize function pointer table with Qualcomm HAL API*/
wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
if (fn == NULL) {
return WIFI_ERROR_UNKNOWN;
}
fn->wifi_initialize = wifi_initialize;
fn->wifi_wait_for_driver_ready = wifi_wait_for_driver_ready;
fn->wifi_cleanup = wifi_cleanup;
fn->wifi_event_loop = wifi_event_loop;
fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
fn->wifi_get_ifaces = wifi_get_ifaces;
fn->wifi_get_iface_name = wifi_get_iface_name;
fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
fn->wifi_start_gscan = wifi_start_gscan;
fn->wifi_stop_gscan = wifi_stop_gscan;
fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
fn->wifi_set_link_stats = wifi_set_link_stats;
fn->wifi_get_link_stats = wifi_get_link_stats;
fn->wifi_clear_link_stats = wifi_clear_link_stats;
fn->wifi_get_valid_channels = wifi_get_valid_channels;
fn->wifi_rtt_range_request = wifi_rtt_range_request;
fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
fn->wifi_enable_responder = wifi_enable_responder;
fn->wifi_disable_responder = wifi_disable_responder;
fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
fn->wifi_start_logging = wifi_start_logging;
fn->wifi_set_epno_list = wifi_set_epno_list;
fn->wifi_reset_epno_list = wifi_reset_epno_list;
fn->wifi_set_country_code = wifi_set_country_code;
fn->wifi_enable_tdls = wifi_enable_tdls;
fn->wifi_disable_tdls = wifi_disable_tdls;
fn->wifi_get_tdls_status = wifi_get_tdls_status;
fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
fn->wifi_set_log_handler = wifi_set_log_handler;
fn->wifi_reset_log_handler = wifi_reset_log_handler;
fn->wifi_set_alert_handler = wifi_set_alert_handler;
fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
fn->wifi_get_firmware_version = wifi_get_firmware_version;
fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
fn->wifi_get_ring_data = wifi_get_ring_data;
fn->wifi_get_driver_version = wifi_get_driver_version;
fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
fn->wifi_set_lci = wifi_set_lci;
fn->wifi_set_lcr = wifi_set_lcr;
fn->wifi_start_sending_offloaded_packet =
wifi_start_sending_offloaded_packet;
fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
fn->wifi_nan_enable_request = nan_enable_request;
fn->wifi_nan_disable_request = nan_disable_request;
fn->wifi_nan_publish_request = nan_publish_request;
fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
fn->wifi_nan_subscribe_request = nan_subscribe_request;
fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
fn->wifi_nan_stats_request = nan_stats_request;
fn->wifi_nan_config_request = nan_config_request;
fn->wifi_nan_tca_request = nan_tca_request;
fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
fn->wifi_nan_register_handler = nan_register_handler;
fn->wifi_nan_get_version = nan_get_version;
fn->wifi_set_packet_filter = wifi_set_packet_filter;
fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
fn->wifi_read_packet_filter = wifi_read_packet_filter;
fn->wifi_nan_get_capabilities = nan_get_capabilities;
fn->wifi_nan_data_interface_create = nan_data_interface_create;
fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
fn->wifi_nan_data_request_initiator = nan_data_request_initiator;
fn->wifi_nan_data_indication_response = nan_data_indication_response;
fn->wifi_nan_data_end = nan_data_end;
fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
fn->wifi_configure_roaming = wifi_configure_roaming;
fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
fn->wifi_set_radio_mode_change_handler = wifi_set_radio_mode_change_handler;
fn->wifi_virtual_interface_create = wifi_virtual_interface_create;
fn->wifi_virtual_interface_delete = wifi_virtual_interface_delete;
fn->wifi_set_latency_mode = wifi_set_latency_mode;
fn->wifi_set_thermal_mitigation_mode = wifi_set_thermal_mitigation_mode;
fn->wifi_set_dtim_config = wifi_set_dtim_config;
return WIFI_SUCCESS;
成功获取到vendor hal接口后,对所有的legacy hal执行初始化
hal->initialize();
该方法目前其实什么都没有做,直接返回WIFI_SUCCESS
// hardware/interface/1.6/default/wifi_legacy_hal.cpp
wifi_error WifiLegacyHal::initialize() {
LOG(DEBUG) << "Initialize legacy HAL";
// this now does nothing, since HAL function table is provided
// to the constructor
return WIFI_SUCCESS;
}
2.1.2 初始化interface
// packages/modules/Wifi/service/java/com/android/server/wifi/WifiNative.java
public String setupInterfaceForClientInScanMode(
@NonNull InterfaceCallback interfaceCallback, @NonNull WorkSource requestorWs) {
// ... ...
Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA_FOR_SCAN);
iface.externalListener = interfaceCallback;
iface.name = createStaIface(iface, requestorWs);
// ... ...
}
allocateIface()
很简单,就是通过WifiNative.IfaceManager新建一个Iface对象.
createStaIface
,这里isVendorHalSupported
不用关注,目前接触到的源码都是支持的,其实现就是去查找halservice列表里面是否包含wifi hal服务
// packages/modules/Wifi/service/java/com/android/server/wifi/WifiNative.java
private String createStaIface(@NonNull Iface iface, @NonNull WorkSource requestorWs) {
synchronized (mLock) {
if (mWifiVendorHal.isVendorHalSupported()) {
return mWifiVendorHal.createStaIface(
new InterfaceDestoyedListenerInternal(iface.id), requestorWs);
} else {
Log.i(TAG, "Vendor Hal not supported, ignoring createStaIface.");
return handleIfaceCreationWhenVendorHalNotSupported(iface);
}
}
}
public String createStaIface(@Nullable InterfaceDestroyedListener destroyedListener,
@NonNull WorkSource requestorWs) {
synchronized (sLock) {
IWifiStaIface iface = mHalDeviceManager.createStaIface(
new StaInterfaceDestroyedListenerInternal(destroyedListener), mHalEventHandler,
requestorWs);
String ifaceName = mHalDeviceManager.getName((IWifiIface) iface);
// 注册android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback,包括onBackgroundScanFailure,onBackgroundFullScanResult,onBackgroundFullScanResults,onRssiThresholdBreached。注册到wifihal
registerStaIfaceCallback(iface);
retrieveWifiChip((IWifiIface) iface);
mIWifiStaIfaces.put(ifaceName, iface);
return ifaceName;
}
}
分析主要方法mHalDeviceManager.createStaIface
HalDeviceManager.java
–> createStaIface(CHIP_CAPABILITY_ANY, destroyedListener, handler, requestorWs)
–> createIface(HDM_CREATE_IFACE_STA, CHIP_CAPABILITY_ANY/*requiredChipCapabilities*/, destroyedListener, handler, requestorWs)
private IWifiIface createIface(@HdmIfaceTypeForCreation int createIfaceType,
long requiredChipCapabilities, InterfaceDestroyedListener destroyedListener,
Handler handler, WorkSource requestorWs) {
synchronized (mLock) {
WifiChipInfo[] chipInfos = getAllChipInfo();
// ... ...
return createIfaceIfPossible(
chipInfos, createIfaceType /* HDM_CREATE_IFACE_STA */, requiredChipCapabilities /* CHIP_CAPABILITY_ANY */,
destroyedListener, handler, requestorWs);
}
}
先获取到所有的chipInfo, 然后通过createIfaceIfPossible
方法选择一个最合适的芯片。
private IWifiIface createIfaceIfPossible(
WifiChipInfo[] chipInfos, @HdmIfaceTypeForCreation int createIfaceType /* HDM_CREATE_IFACE_STA */,
long requiredChipCapabilities/* CHIP_CAPABILITY_ANY */, InterfaceDestroyedListener destroyedListener,
Handler handler, WorkSource requestorWs) {
int targetHalIfaceType = HAL_IFACE_MAP.get(createIfaceType);
synchronized (mLock) {
IfaceCreationData bestIfaceCreationProposal = getBestIfaceCreationProposal(chipInfos,
createIfaceType, requiredChipCapabilities, requestorWs);
if (bestIfaceCreationProposal != null) {
IWifiIface iface = executeChipReconfiguration(bestIfaceCreationProposal,
createIfaceType /* HDM_CREATE_IFACE_STA */);
// ... ...
return iface;
}
}
return null
}
主要两个方法:
-
getBestIfaceCreationProposal
获取最合适的iface
暂时不分析,因为目前我们都是单芯片
-
executeChipReconfiguration
配置iface
着重看一下executeChipReconfiguration
方法
private IWifiIface executeChipReconfiguration(IfaceCreationData ifaceCreationData,
@HdmIfaceTypeForCreation int createIfaceType) {
// ... ...
switch (createIfaceType) {
case HDM_CREATE_IFACE_STA:
ifaceCreationData.chipInfo.chip.createStaIface(
(WifiStatus status, IWifiStaIface iface) -> {
statusResp.value = status;
ifaceResp.value = iface;
});
break;
// ... ...
}
// ... ...
updateRttControllerWhenInterfaceChanges();
return ifaceResp.value;
}
ifaceCreationData.chipInfo.chip.createStaIface()
就调用到了WiFi HAL
// hardware/interfaces/wifi/1.6/default/wifi_chip.cpp
Return<void> WifiChip::createStaIface(createStaIface_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::createStaIfaceInternal, hidl_status_cb);
}
createStaIfaceInternal()
分为下面几步
-
allocateStaIfaceName()
获取 interface name,在我的平台上是通过属性来配置的。如果vendor hal支持wifi_get_supported_iface_name()
接口的话,优先从vendor hal获取iface name,否则通过属性wifi.interface
或wifi.interface.0
device/oneplus/sdm845-common/rootdir/etc/init.qcom.rc: setprop wifi.interface wlan0
-
createVirtualInterface()
创建interface调用vendor hal的
wifi_virtual_interface_create()
,通过nl80211接口创建interface。参考 http://aospxref.com/android-13.0.0_r3/xref/hardware/qcom/wlan/qcwcn/wifi_hal/wificonfig.cpp#821
至此,wifi的interface已经创建成功了。
2.1.3 wificond初始化
经过上面的第1和2步,驱动和hal已经成功加载,而且interface也已经创建好了。
接下来是通过WifiNl80211Manager
的setupInterfaceForClientMode()
方法来配置。
public boolean setupInterfaceForClientMode(@NonNull String ifaceName,
@NonNull @CallbackExecutor Executor executor,
@NonNull ScanEventCallback scanCallback, @NonNull ScanEventCallback pnoScanCallback) {
// 1. 获取 WIFI_NL80211_SERVICE(wifinl80211)
retrieveWificondAndRegisterForDeath();
// 2. wificond对ifaceName代表的网卡进行初始化,返回了一个ClientInterfaceImpl的代理ClientInterfaceBinder (system/connectivity/wificond/client_interface_binder.cpp)
IClientInterface clientInterface = mWificond.createClientInterface(ifaceName);
mClientInterfaces.put(ifaceName, clientInterface);
// 3. subscribeScanEvents, subscribePnoScanEvents
IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl();
mWificondScanners.put(ifaceName, wificondScanner);
canEventHandler scanEventHandler = new ScanEventHandler(executor, scanCallback);
mScanEventHandlers.put(ifaceName, scanEventHandler);
wificondScanner.subscribeScanEvents(scanEventHandler);
PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(executor,
pnoScanCallback);
mPnoScanEventHandlers.put(ifaceName, pnoScanEventHandler);
wificondScanner.subscribePnoScanEvents(pnoScanEventHandler);
}
wificond(wifi connectivity daemon)目前在只支持网卡配置和扫描,连接还是通过wpa_supplicant.
wificond的代码这里不展开,核心是通过netlink跟内核nl80211模块通信,用于管理 Wi-Fi 硬件和提供 Wi-Fi 相关的信息和控制功能。
至此,通过1,2,3 驱动和HAL都加载完毕,网卡也创建并初始化成功,主要负责管理wifi以及扫描的wificond模块也已经初始化成功。
所以为什么叫setupInterfaceForClientInScanMode,因为到目前为止,还不能为上层提供连接功能,只能扫描。
接下来就是启动提供连接功能的wpa_supplicant进程
2.2 switchClientInterfaceToConnectivityMode 启动supplicant
// packages/modules/Wifi/service/java/com/android/server/wifi/WifiNative.java
public boolean switchClientInterfaceToConnectivityMode(@NonNull String ifaceName,
@NonNull WorkSource requestorWs) {
// ... ...
startSupplicant();
// ... ...
mSupplicantStaIfaceHal.setupIface(iface.name);
// ... ...
}
2.2.1 启动supplicant
startSupplicant() --> startAndWaitForSupplicantConnection()
private boolean startAndWaitForSupplicantConnection() {
// Start initialization if not already started.
if (!mSupplicantStaIfaceHal.isInitializationStarted()
&& !mSupplicantStaIfaceHal.initialize()) {
return false;
}
if (!mSupplicantStaIfaceHal.startDaemon()) {
Log.e(TAG, "Failed to startup supplicant");
return false;
}
boolean connected = false;
int connectTries = 0;
while (!connected && connectTries++ < CONNECT_TO_SUPPLICANT_RETRY_TIMES) {
// Check if the initialization is complete.
connected = mSupplicantStaIfaceHal.isInitializationComplete();
if (connected) {
break;
}
try {
Thread.sleep(CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS);
} catch (InterruptedException ignore) {
}
}
return connected;
}
这个函数很简单,调用mSupplicantStaIfaceHal.startDaemon()
启动supplicant;然后每CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS
100ms检查一次,最多检查50次,通过方法mSupplicantStaIfaceHal.isInitializationComplete()
检查supplicant是否成功启动。
Supplicant启动: SupplicantStaIfaceHal.startDaemon() --> ISupplicantStaIfaceHal.startDaemon() --> SupplicantStaIfaceHalAidlImpl
// packages/modules/Wifi/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java
public boolean startDaemon() {
final String methodStr = "startDaemon";
if (mISupplicant != null) {
Log.i(TAG, "Service is already initialized, skipping " + methodStr);
return true;
}
mISupplicant = getSupplicantMockable();
if (mISupplicant == null) {
Log.e(TAG, "Unable to obtain ISupplicant binder.");
return false;
}
Log.i(TAG, "Obtained ISupplicant binder.");
try {
IBinder serviceBinder = getServiceBinderMockable();
if (serviceBinder == null) {
return false;
}
serviceBinder.linkToDeath(mSupplicantDeathRecipient, /* flags= */ 0);
return true;
} catch (RemoteException e) {
handleRemoteException(e, methodStr);
return false;
}
}
主要方法getSupplicantMockable()
private static final String HAL_INSTANCE_NAME = ISupplicant.DESCRIPTOR + "/default";
protected ISupplicant getSupplicantMockable() {
synchronized (mLock) {
try {
return ISupplicant.Stub.asInterface(
ServiceManager.waitForDeclaredService(HAL_INSTANCE_NAME));
} catch (Exception e) {
Log.e(TAG, "Unable to get ISupplicant service, " + e);
return null;
}
}
}
supplicant的service名称展开android.hardware.wifi.supplicant.ISupplicant/default
. 由于wifi关闭后,wpa_supplicant会退出,所以此时再次打开是无法找到该service的,需要系统把它拉起来
09-12 17:09:38.988 645 645 I servicemanager: Found android.hardware.wifi.supplicant.ISupplicant/default in device VINTF manifest.
09-12 17:09:38.988 645 645 I servicemanager: Since 'android.hardware.wifi.supplicant.ISupplicant/default' could not be found, trying to start it as a lazy AIDL service
09-12 17:09:38.514 0 0 I init : starting service 'wpa_supplicant'...
09-12 17:09:38.527 0 0 I init : Control message: Processed ctl.interface_start for 'aidl/android.hardware.wifi.supplicant.ISupplicant/default' from pid: 645 (/system/bin/servicemanager)
supplicant hal的rc文件(/vendor/etc/init/android.hardware.wifi.supplicant-service.rc)定义如下
service wpa_supplicant /vendor/bin/hw/wpa_supplicant \
-O/data/vendor/wifi/wpa/sockets -dd \
-g@android:wpa_wlan0
# we will start as root and wpa_supplicant will switch to user wifi
# after setting up the capabilities required for WEXT
# user wifi
# group wifi inet keystore
interface aidl android.hardware.wifi.supplicant.ISupplicant/default
class main
socket wpa_wlan0 dgram 660 wifi wifi
disabled
oneshot
此时 SupplicantStaIfaceHalAidlImpl
已经将supplicnat进程成功拉起,并且与supplicant hal service进行了绑定。后面如果需要与supplicant通信,那么Frameowork层就直接通过SupplicantStaIfaceHalAidlImpl
调用其接口就行。
3. ClientModeImpl发起扫描
进入初始状态 DisconnectedState 后立即发起 connectivity scan
DisconnectedState.enter() {
mWifiConnectivityManager.handleConnectionStateChanged(
mClientModeManager,
WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
}
我们看看handleConnectionStateChanged方法在disconnected的时候做了什么
public void handleConnectionStateChanged(
ConcreteClientModeManager clientModeManager, int state) {
if (mWifiState == WIFI_STATE_DISCONNECTED) {
scheduleWatchdogTimer();
// Switch to the disconnected scanning schedule
setSingleScanningSchedule(mDisconnectedSingleScanScheduleSec);
setSingleScanningType(mDisconnectedSingleScanType);
startConnectivityScan(SCAN_IMMEDIATELY);
}
}
mDisconnectedSingleScanScheduleSec: 默认 {20, 40, 80, 160},可以通过config_wifiDisconnectedScanIntervalScheduleSec自定义
mDisconnectedSingleScanType: 默认WifiScanner.SCAN_TYPE_HIGH_ACCURACY
最后调用startConnectivityScan()接口直接发起扫描
4. 状态机流程
文章来源:https://www.toymoban.com/news/detail-769320.html
5. 总结
待补充文章来源地址https://www.toymoban.com/news/detail-769320.html
到了这里,关于Android WiFi 开启流程(基于Android S)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!