Android WiFi 开启流程(基于Android S)

这篇具有很好参考价值的文章主要介绍了Android WiFi 开启流程(基于Android S)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文介绍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.interfacewifi.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也已经创建好了。

接下来是通过WifiNl80211ManagersetupInterfaceForClientMode()方法来配置。

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. 状态机流程

android 打开wifi,开发语言,android,网络,网络协议

5. 总结

待补充文章来源地址https://www.toymoban.com/news/detail-769320.html

到了这里,关于Android WiFi 开启流程(基于Android S)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 12 Wifi 开发(获取列表、连接、断开连接)

    获取Wifi列表: 扫描(这个方法早在Android 9.0 就被弃用), 不过如果不调用的话是没法及时获取Wifi列表的广播的。 (不需要也能正常获取,没有延迟,经实验毫无区别) 创建广播并接收: 配置并连接( 无系统签名 ): 配置并连接( 有系统签名 ): 断开连接(无系统签名

    2024年02月03日
    浏览(25)
  • 嵌入式Linux&Android开发-WiFi&BT SDIO调试

    目录   一、基本概念 WiFi STA 模式 和 AP 模式 SDIO(Secure Digital I/O) SDIO-WiFi 模块 二、项目中WiFi说明 三、rockchip WiFi启动流程简介 WiFi应用部分 wpa_supplicant 四、RK WiFi驱动移植流程 4.1 BSP已支持WiFi 4.2 BSP未支持WiFi 五、排查流程 5.1 检查DTS 5.2 排查DTS对应的GPIO设置 5.3检查电压电平

    2023年04月08日
    浏览(52)
  • 【Android13开发WIFI添加频段设置项(2.4G/5G/automatic)更改笔记】

    提示:这里简述项目相关背景: Android13中客户需求添加WIFI频段选项: 2.4G only,只显示链接2.4G的AP。 5G only,只能显示和链接5G的AP。 Automatic:自动显示,即全部正常显示。 提示:这里描述项目中遇到的问题: 作为初学者的我,刚开始接到这个bug,还是比较懵的,多亏了CSDN的前辈

    2024年02月05日
    浏览(32)
  • Android WiFi Service启动-Android13

    Android WiFi基础概览 AOSP 文档 心主题 WiFi概览 编译生成对应的jar包: \\\"/apex/com.android.wifi/javalib/service-wifi.jar\\\" 相关WiFi服务: WifiService 、 WifiScanningService 、 RttService 、 WifiAwareService 、 WifiP2pService frameworks/base/services/java/com/android/server/SystemServer.java WifiInjector.java : WiFi依赖性注入器。

    2024年01月21日
    浏览(31)
  • android连接指定wifi

    在Android设备上,我们可以通过代码连接到特定的WiFi网络。这在许多应用中都是非常有用的,例如自动连接到家庭WiFi网络,或者在商家的应用中连接到特定店铺的WiFi网络。 本文将教您如何使用Android代码连接到指定的WiFi网络,并提供示例代码来帮助您实现此功能。 前提条件

    2024年01月16日
    浏览(31)
  • android通过代码连接wifi

    Android SDK API 29(对应Android 10)以下,可以在app之中通过代码直接设置wifi名称和密码进行连接。 API 29及其以上版本,增加了动态管理权限功能,弃用了之前的接口,同时app连接wifi时必须通过用户同意,具体方式是弹出一个页面显示要连接的wifi,用户点击连接之后再返回app。

    2024年02月20日
    浏览(26)
  • Android adb wifi调试

    0、需要先配置adb的环境变量。打开电脑的环境变量的设置,增加Path的路径,输入sdk下的这个位置(D:androidsdkplatform-tools),如果能在windows上使用adb命令,但是Android Studio中不行,重启as也不行的情况下,那就得重启电脑(cmd 中能用adb,terminal中就不能用,两字:重启电脑)配

    2024年02月06日
    浏览(38)
  • Android13 wifi状态问题分析

    场景; 设置wif 默认开关属性: 系统升级后,wifi 默认设置属性无效。 原因: 多个地方存在定义默认wifi开关状态的定义。 解决方法: 可能是配置文件,有overlay,一般是在 vendor 下面有 WifiOverlay的情况,或者全局查找,使用命令查找: 看看系统源码哪里还会设置默认状态的

    2024年02月01日
    浏览(28)
  • Android扫码连接WIFI实现

    0,目标         APP中实现扫WIFI分享码自动连接WIFI功能 1,前提条件         设备需要有个扫码器(摄像头拍照识别也行),APP调用扫码器读取WIFI连接分享码。 2,增加权限         在AndroidManifest.xml中增加权限 3,参数检查         扫码成功后,对内容进行一个

    2024年02月09日
    浏览(24)
  • Android app应用连接WiFi的方法(兼容Android10)

    Android应用开发有时候会有应用直连app的需求,由于Android系统 api会时常变动,wifi连接api亦如此,Android10以下直接使用: Android 10以上则可以使用 或是WifiNetworkSuggestion 方式 最后分享工具类

    2024年02月04日
    浏览(71)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包