前言:之前在 (四十四)Android O WiFi启动流程梳理 梳理到了WifiNative的setupForClientMode ,没有继续梳理下去,现在接着梳理。
参考:
Android wifi打开流程(Android O)
hidl:
1.https://source.android.com/devices/architecture/hidl/
2.https://blog.csdn.net/qidi_huang/article/details/76572404
setupForClientMode
/**
* Setup wifi native for Client mode operations.
*
* 1. Starts the Wifi HAL and configures it in client/STA mode.
* 2. Setup Wificond to operate in client mode and retrieve the handle to use for client
* operations.
*
* @return Pair of to indicate the status and the associated wificond
* client interface binder handler (will be null on failure).
*/
public Pair setupForClientMode() {
if (!startHalIfNecessary(true)) {
Log.e(mTAG, "Failed to start HAL for client mode");
return Pair.create(SETUP_FAILURE_HAL, null);
}
IClientInterface iClientInterface = mWificondControl.setupDriverForClientMode();
if (iClientInterface == null) {
return Pair.create(SETUP_FAILURE_WIFICOND, null);
}
return Pair.create(SETUP_SUCCESS, iClientInterface);
}
startHalIfNecessary
/**
* Bring up the Vendor HAL and configure for STA mode or AP mode, if vendor HAL is supported.
*
* @param isStaMode true to start HAL in STA mode, false to start in AP mode.
* @return false if the HAL start fails, true if successful or if vendor HAL not supported.
*/
private boolean startHalIfNecessary(boolean isStaMode) {
if (!mWifiVendorHal.isVendorHalSupported()) {
Log.i(mTAG, "Vendor HAL not supported, Ignore start...");
return true;
}
return mWifiVendorHal.startVendorHal(isStaMode);
}
startVendorHal
/**
* Bring up the HIDL Vendor HAL and configure for STA mode or AP mode.
*
* @param isStaMode true to start HAL in STA mode, false to start in AP mode.
*/
public boolean startVendorHal(boolean isStaMode) {
synchronized (sLock) {
if (mIWifiStaIface != null) return boolResult(false);
if (mIWifiApIface != null) return boolResult(false);
if (!mHalDeviceManager.start()) {
return startFailedTo("start the vendor HAL");
}
IWifiIface iface;
if (isStaMode) {
mIWifiStaIface = mHalDeviceManager.createStaIface(null, null);
if (mIWifiStaIface == null) {
return startFailedTo("create STA Iface");
}
iface = (IWifiIface) mIWifiStaIface;
if (!registerStaIfaceCallback()) {
return startFailedTo("register sta iface callback");
}
mIWifiRttController = mHalDeviceManager.createRttController(iface);
if (mIWifiRttController == null) {
return startFailedTo("create RTT controller");
}
if (!registerRttEventCallback()) {
return startFailedTo("register RTT iface callback");
}
enableLinkLayerStats();
} else {
mIWifiApIface = mHalDeviceManager.createApIface(null, null);
if (mIWifiApIface == null) {
return startFailedTo("create AP Iface");
}
iface = (IWifiIface) mIWifiApIface;
}
mIWifiChip = mHalDeviceManager.getChip(iface);
if (mIWifiChip == null) {
return startFailedTo("get the chip created for the Iface");
}
if (!registerChipCallback()) {
return startFailedTo("register chip callback");
}
mLog.i("Vendor Hal started successfully");
return true;
}
}
先看下HalDeviceManager的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();
}
startWifi
private boolean startWifi() {
if (DBG) 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;
}
}
}
看下mWifi是什么
/**
* Wrapper function to access the HIDL services. Created to be mockable in unit-tests.
*/
protected IWifi getWifiServiceMockable() {
try {
return IWifi.getService();
} catch (RemoteException e) {
Log.e(TAG, "Exception getting IWifi service: " + e);
return null;
}
}
hidl对应的服务端。
IWifi服务器端的探索
看下IWifi的导包:import android.hardware.wifi.V1_0.IWifi;
然后全局搜了下代码发现:
结合(六十八) HIDL C++ 软件包这张图:
对应在out目录下生成的:
/out/soong/.intermediates/hardware/interfaces/wifi/1.0/[email protected]_genc++_headers/gen/android/hardware/wifi/1.0
目录结构和之前看到的aidl-cpp有点类似。
之后参考
Android.mk或者Android.bp里找一下是否有依赖[email protected]的
没找到特别像的,之后找到/hardware/interfaces/wifi/1.0/Android.mk有如下配置
#
# Build IWifi.hal
#
GEN := $(intermediates)/android/hardware/wifi/V1_0/IWifi.java
$(GEN): $(HIDL)
$(GEN): PRIVATE_HIDL := $(HIDL)
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IWifi.hal
$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IWifiChip.hal
$(GEN): $(LOCAL_PATH)/IWifiChip.hal
$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IWifiEventCallback.hal
$(GEN): $(LOCAL_PATH)/IWifiEventCallback.hal
$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
$(GEN): $(LOCAL_PATH)/types.hal
$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
$(GEN): PRIVATE_CUSTOM_TOOL = \
$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-Ljava \
-randroid.hardware:hardware/interfaces \
-randroid.hidl:system/libhidl/transport \
[email protected]::IWifi
$(GEN): $(LOCAL_PATH)/IWifi.hal
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
我在out目录还搜索到了IWifi.java
.out/target/common/gen/JAVA_LIBRARIES/android.hardware.wifi-V1.0-java_intermediates/android/hardware/wifi/V1_0/IWifi.java
.out/target/common/gen/JAVA_LIBRARIES/android.hardware.wifi-V1.1-java_intermediates/android/hardware/wifi/V1_1/IWifi.java
然后看下IWifi.java的getService方法
public static IWifi getService(String serviceName) throws android.os.RemoteException {
return IWifi.asInterface(android.os.HwBinder.getService("[email protected]::IWifi",serviceName));
}
看起来和getSystemService很像。
加深下理解:
WiFi启动后有如下进程:
root 360 1 17916 4864 0 0 S [email protected]
而获取service则是
IWifi.asInterface(android.os.HwBinder.getService("[email protected]::IWifi",serviceName));
可以理解是将[email protected]中IWifi对应的服务端返回了么。
那么IWifi的服务端,参考(八十一)探索hidl-gen使用及IWifi.hal 实现 应该是Wifi.cpp和Wifi.h
那对应的实现方法:
Return Wifi::start(start_cb hidl_status_cb) {
return validateAndCall(this,
WifiStatusCode::ERROR_UNKNOWN,
&Wifi::startInternal,
hidl_status_cb);
WifiStatus Wifi::startInternal() {
if (run_state_ == RunState::STARTED) {
return createWifiStatus(WifiStatusCode::SUCCESS);
} else if (run_state_ == RunState::STOPPING) {
return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
"HAL is stopping");
}
WifiStatus wifi_status = initializeLegacyHal();
if (wifi_status.code == WifiStatusCode::SUCCESS) {
// Create the chip instance once the HAL is started.
chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_);
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";
} else {
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onFailure(wifi_status).isOk()) {
LOG(ERROR) << "Failed to invoke onFailure callback";
}
}
LOG(ERROR) << "Wifi HAL start failed";
}
return wifi_status;
}
WifiStatus Wifi::initializeLegacyHal() {
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_legacy_hal.cpp
wifi_error WifiLegacyHal::initialize() {
LOG(DEBUG) << "Initialize legacy HAL";
// TODO: Add back the HAL Tool if we need to. All we need from the HAL tool
// for now is this function call which we can directly call.
if (!initHalFuncTableWithStubs(&global_func_table_)) {
LOG(ERROR) << "Failed to initialize legacy hal function table with stubs";
return WIFI_ERROR_UNKNOWN;
}
wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_);
if (status != WIFI_SUCCESS) {
LOG(ERROR) << "Failed to initialize legacy hal function table";
}
return status;
}
init_wifi_vendor_hal_func_table这个方法对应于:
frameworks/opt/net/wifi / libwifi_hal/Android.mk中的libwifi-hal-fallback/libwifi-hal-bcm/libwifi-hal-qcom/libwifi-hal-mt66xx,具体配置为mtk/高通还是啥取决于配置。
# A fallback "vendor" HAL library.
# Don't link this, link libwifi-hal.
# ============================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libwifi-hal-fallback
LOCAL_VENDOR_MODULE := true
LOCAL_CFLAGS := $(wifi_hal_cflags)
LOCAL_SRC_FILES := wifi_hal_fallback.cpp
LOCAL_HEADER_LIBRARIES := libhardware_legacy_headers
include $(BUILD_STATIC_LIBRARY)
# Pick a vendor provided HAL implementation library.
# ============================================================
LIB_WIFI_HAL := libwifi-hal-fallback
VENDOR_LOCAL_SHARED_LIBRARIES :=
ifeq ($(BOARD_WLAN_DEVICE), bcmdhd)
LIB_WIFI_HAL := libwifi-hal-bcm
else ifeq ($(BOARD_WLAN_DEVICE), qcwcn)
LIB_WIFI_HAL := libwifi-hal-qcom
VENDOR_LOCAL_SHARED_LIBRARIES := libcld80211
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
endif
# The WiFi HAL that you should be linking.
# ============================================================
include $(CLEAR_VARS)
LOCAL_MODULE := libwifi-hal
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-fallback是not_support,会导致之前wifi_legacy_hal.cpp初始化失败。
#include "hardware_legacy/wifi_hal.h"
wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
return WIFI_ERROR_NOT_SUPPORTED;
}
这里以高通的为例:
/aosp/android_aosp/hardware/qcom/wlan/qcwcn/wifi_hal
/*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_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_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;
return WIFI_SUCCESS;
}
/**
* Create a STA interface if possible. Changes chip mode and removes conflicting interfaces if
* needed and permitted by priority.
*
* @param destroyedListener Optional (nullable) listener to call when the allocated interface
* is removed. Will only be registered and used if an interface is
* created successfully.
* @param looper The looper on which to dispatch the listener. A null value indicates the
* current thread.
* @return A newly created interface - or null if the interface could not be created.
*/
public IWifiStaIface createStaIface(InterfaceDestroyedListener destroyedListener,
Looper looper) {
return (IWifiStaIface) createIface(IfaceType.STA, destroyedListener, looper);
}
private IWifiIface createIface(int ifaceType, InterfaceDestroyedListener destroyedListener,
Looper looper) {
if (DBG) Log.d(TAG, "createIface: ifaceType=" + ifaceType);
synchronized (mLock) {
WifiChipInfo[] chipInfos = getAllChipInfo();
if (chipInfos == null) {
Log.e(TAG, "createIface: no chip info found");
stopWifi(); // major error: shutting down
return null;
}
if (!validateInterfaceCache(chipInfos)) {
Log.e(TAG, "createIface: local cache is invalid!");
stopWifi(); // major error: shutting down
return null;
}
IWifiIface iface = createIfaceIfPossible(chipInfos, ifaceType, destroyedListener,
looper);
if (iface != null) { // means that some configuration has changed
if (!dispatchAvailableForRequestListeners()) {
return null; // catastrophic failure - shut down
}
}
return iface;
}
}
private IWifiIface createIfaceIfPossible(WifiChipInfo[] chipInfos, int ifaceType,
InterfaceDestroyedListener destroyedListener, Looper looper) {
if (DBG) {
Log.d(TAG, "createIfaceIfPossible: chipInfos=" + Arrays.deepToString(chipInfos)
+ ", ifaceType=" + ifaceType);
}
synchronized (mLock) {
IfaceCreationData bestIfaceCreationProposal = null;
for (WifiChipInfo chipInfo: chipInfos) {
for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) {
for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode
.availableCombinations) {
int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo);
if (DBG) {
Log.d(TAG, chipIfaceCombo + " expands to "
+ Arrays.deepToString(expandedIfaceCombos));
}
for (int[] expandedIfaceCombo: expandedIfaceCombos) {
IfaceCreationData currentProposal = canIfaceComboSupportRequest(
chipInfo, chipMode, expandedIfaceCombo, ifaceType);
if (compareIfaceCreationData(currentProposal,
bestIfaceCreationProposal)) {
if (DBG) Log.d(TAG, "new proposal accepted");
bestIfaceCreationProposal = currentProposal;
}
}
}
}
}
if (bestIfaceCreationProposal != null) {
IWifiIface iface = executeChipReconfiguration(bestIfaceCreationProposal, ifaceType);
if (iface != null) {
InterfaceCacheEntry cacheEntry = new InterfaceCacheEntry();
cacheEntry.chip = bestIfaceCreationProposal.chipInfo.chip;
cacheEntry.chipId = bestIfaceCreationProposal.chipInfo.chipId;
cacheEntry.name = getName(iface);
cacheEntry.type = ifaceType;
if (destroyedListener != null) {
cacheEntry.destroyedListeners.add(
new InterfaceDestroyedListenerProxy(destroyedListener,
looper == null ? Looper.myLooper() : looper));
}
if (DBG) Log.d(TAG, "createIfaceIfPossible: added cacheEntry=" + cacheEntry);
mInterfaceInfoCache.put(cacheEntry.name, cacheEntry);
return iface;
}
}
}
return null;
}
/**
* Performs chip reconfiguration per the input:
* - Removes the specified interfaces
* - Reconfigures the chip to the new chip mode (if necessary)
* - Creates the new interface
*
* Returns the newly created interface or a null on any error.
*/
private IWifiIface executeChipReconfiguration(IfaceCreationData ifaceCreationData,
int ifaceType) {
if (DBG) {
Log.d(TAG, "executeChipReconfiguration: ifaceCreationData=" + ifaceCreationData
+ ", ifaceType=" + ifaceType);
}
synchronized (mLock) {
try {
// is this a mode change?
boolean isModeConfigNeeded = !ifaceCreationData.chipInfo.currentModeIdValid
|| ifaceCreationData.chipInfo.currentModeId != ifaceCreationData.chipModeId;
if (DBG) Log.d(TAG, "isModeConfigNeeded=" + isModeConfigNeeded);
// first delete interfaces/change modes
if (isModeConfigNeeded) {
// remove all interfaces pre mode-change
// TODO: is this necessary? note that even if we don't want to explicitly
// remove the interfaces we do need to call the onDeleted callbacks - which
// this does
for (WifiIfaceInfo[] ifaceInfos: ifaceCreationData.chipInfo.ifaces) {
for (WifiIfaceInfo ifaceInfo: ifaceInfos) {
removeIfaceInternal(ifaceInfo.iface); // ignore return value
}
}
WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip(
ifaceCreationData.chipModeId);
if (status.code != WifiStatusCode.SUCCESS) {
Log.e(TAG, "executeChipReconfiguration: configureChip error: "
+ statusString(status));
return null;
}
} else {
// remove all interfaces on the delete list
for (WifiIfaceInfo ifaceInfo: ifaceCreationData.interfacesToBeRemovedFirst) {
removeIfaceInternal(ifaceInfo.iface); // ignore return value
}
}
// create new interface
Mutable statusResp = new Mutable<>();
Mutable ifaceResp = new Mutable<>();
switch (ifaceType) {
case IfaceType.STA:
ifaceCreationData.chipInfo.chip.createStaIface(
(WifiStatus status, IWifiStaIface iface) -> {
statusResp.value = status;
ifaceResp.value = iface;
});
break;
case IfaceType.AP:
ifaceCreationData.chipInfo.chip.createApIface(
(WifiStatus status, IWifiApIface iface) -> {
statusResp.value = status;
ifaceResp.value = iface;
});
break;
case IfaceType.P2P:
ifaceCreationData.chipInfo.chip.createP2pIface(
(WifiStatus status, IWifiP2pIface iface) -> {
statusResp.value = status;
ifaceResp.value = iface;
});
break;
case IfaceType.NAN:
ifaceCreationData.chipInfo.chip.createNanIface(
(WifiStatus status, IWifiNanIface iface) -> {
statusResp.value = status;
ifaceResp.value = iface;
});
break;
}
if (statusResp.value.code != WifiStatusCode.SUCCESS) {
Log.e(TAG, "executeChipReconfiguration: failed to create interface ifaceType="
+ ifaceType + ": " + statusString(statusResp.value));
return null;
}
return ifaceResp.value;
} catch (RemoteException e) {
Log.e(TAG, "executeChipReconfiguration exception: " + e);
return null;
}
}
}
hardware/interfaces/wifi/1.1/default/wifi_chip.cpp
Return WifiChip::configureChip(ChipModeId mode_id,
configureChip_cb hidl_status_cb) {
return validateAndCall(this,
WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::configureChipInternal,
hidl_status_cb,
mode_id);
}
WifiStatus WifiChip::configureChipInternal(ChipModeId mode_id) {
if (mode_id != kStaChipModeId && mode_id != kApChipModeId) {
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
}
if (mode_id == current_mode_id_) {
LOG(DEBUG) << "Already in the specified mode " << mode_id;
return createWifiStatus(WifiStatusCode::SUCCESS);
}
WifiStatus status = handleChipConfiguration(mode_id);
if (status.code != WifiStatusCode::SUCCESS) {
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onChipReconfigureFailure(status).isOk()) {
LOG(ERROR) << "Failed to invoke onChipReconfigureFailure callback";
}
}
return status;
}
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onChipReconfigured(mode_id).isOk()) {
LOG(ERROR) << "Failed to invoke onChipReconfigured callback";
}
}
current_mode_id_ = mode_id;
return status;
}
WifiStatus WifiChip::handleChipConfiguration(ChipModeId mode_id) {
// If the chip is already configured in a different mode, stop
// the legacy HAL and then start it after firmware mode change.
// Currently the underlying implementation has a deadlock issue.
// We should return ERROR_NOT_SUPPORTED if chip is already configured in
// a different mode.
if (current_mode_id_ != kInvalidModeId) {
// TODO(b/37446050): Fix the deadlock.
return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
}
bool success;
if (mode_id == kStaChipModeId) {
success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);
} else {
success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);
}
if (!success) {
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
}
legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
LOG(ERROR) << "Failed to start legacy HAL: "
<< legacyErrorToString(legacy_status);
return createWifiStatusFromLegacyError(legacy_status);
}
return createWifiStatus(WifiStatusCode::SUCCESS);
}
这里稍微看下legacy_hal_.lock()->start()
之前legacy_hal在wifi start过程中被初始化了,这边会调用其start方法
wifi_legacy_hal.cpp
wifi_error WifiLegacyHal::start() {
// Ensure that we're starting in a good state.
CHECK(global_func_table_.wifi_initialize && !global_handle_ &&
!wlan_interface_handle_ && !awaiting_event_loop_termination_);
if (is_started_) {
LOG(DEBUG) << "Legacy HAL already started";
return WIFI_SUCCESS;
}
LOG(DEBUG) << "Starting legacy HAL";
if (!iface_tool_.SetWifiUpState(true)) {
LOG(ERROR) << "Failed to set WiFi interface up";
return WIFI_ERROR_UNKNOWN;
}
wifi_error status = global_func_table_.wifi_initialize(&global_handle_);
if (status != WIFI_SUCCESS || !global_handle_) {
LOG(ERROR) << "Failed to retrieve global handle";
return status;
}
std::thread(&WifiLegacyHal::runEventLoop, this).detach();
status = retrieveWlanInterfaceHandle();
if (status != WIFI_SUCCESS || !wlan_interface_handle_) {
LOG(ERROR) << "Failed to retrieve wlan interface handle";
return status;
}
LOG(DEBUG) << "Legacy HAL start complete";
is_started_ = true;
return WIFI_SUCCESS;
}
之前我们假设的global_func_table是qcom
wifi_error wifi_initialize(wifi_handle *handle)
{
int err = 0;
wifi_error ret = WIFI_SUCCESS;
wifi_interface_handle iface_handle;
struct nl_sock *cmd_sock = NULL;
struct nl_sock *event_sock = NULL;
struct nl_cb *cb = NULL;
int status = 0;
ALOGI("Initializing wifi");
hal_info *info = (hal_info *)malloc(sizeof(hal_info));
if (info == NULL) {
ALOGE("Could not allocate hal_info");
return WIFI_ERROR_OUT_OF_MEMORY;
}
memset(info, 0, sizeof(*info));
cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
NETLINK_GENERIC);
if (cmd_sock == NULL) {
ALOGE("Failed to create command socket port");
ret = WIFI_ERROR_UNKNOWN;
goto unload;
}
/* Set the socket buffer size */
if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
strerror(errno));
/* continue anyway with the default (smaller) buffer */
}
event_sock =
wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
if (event_sock == NULL) {
ALOGE("Failed to create event socket port");
ret = WIFI_ERROR_UNKNOWN;
goto unload;
}
/* Set the socket buffer size */
if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
strerror(errno));
/* continue anyway with the default (smaller) buffer */
}
cb = nl_socket_get_cb(event_sock);
if (cb == NULL) {
ALOGE("Failed to get NL control block for event socket port");
ret = WIFI_ERROR_UNKNOWN;
goto unload;
}
err = 1;
nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
。。。
ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
" features : %x", NL80211_CMD_VENDOR, info->supported_feature_set);
cld80211_cleanup:
if (status != 0 || ret != WIFI_SUCCESS) {
ret = WIFI_ERROR_UNKNOWN;
cld80211lib_cleanup(info);
}
unload:
if (ret != WIFI_SUCCESS) {
if (cmd_sock)
nl_socket_free(cmd_sock);
if (event_sock)
nl_socket_free(event_sock);
if (info) {
if (info->cmd) free(info->cmd);
if (info->event_cb) free(info->event_cb);
if (info->cldctx) {
cld80211lib_cleanup(info);
} else if (info->user_sock) {
nl_socket_free(info->user_sock);
}
if (info->pkt_stats) free(info->pkt_stats);
if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
cleanupGscanHandlers(info);
cleanupRSSIMonitorHandler(info);
free(info);
}
}
return ret;
}
bool WifiModeController::changeFirmwareMode(IfaceType type) {
if (!driver_tool_->LoadDriver()) {
LOG(ERROR) << "Failed to load WiFi driver";
return false;
}
if (!driver_tool_->ChangeFirmwareMode(convertIfaceTypeToFirmwareMode(type))) {
LOG(ERROR) << "Failed to change firmware mode";
return false;
}
return true;
}
frameworks/opt/net/wifi/libwifi_hal/driver_tool.cpp
bool DriverTool::LoadDriver() {
return ::wifi_load_driver() == 0;
}
bool DriverTool::ChangeFirmwareMode(int mode) {
const char* fwpath = wifi_get_fw_path(mode);
if (!fwpath) {
return true; // HAL doesn't think we need to load firmware for this mode.
}
if (wifi_change_fw_path(fwpath) != 0) {
// Not all devices actually require firmware reloads, but
// failure to change the firmware path when it is defined is an error.
return false;
}
return true;
}
frameworks/opt/net/wifi/libwifi_hal/wifi_hal_common.cpp
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;
}
#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
int wifi_change_driver_state(const char *state) {
int len;
int fd;
int ret = 0;
if (!state) return -1;
fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY));
if (fd < 0) {
PLOG(ERROR) << "Failed to open driver state control param";
return -1;
}
len = strlen(state) + 1;
if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) {
PLOG(ERROR) << "Failed to write driver state control param";
ret = -1;
}
close(fd);
return ret;
}
#endif
const char *wifi_get_fw_path(int fw_type) {
switch (fw_type) {
case WIFI_GET_FW_PATH_STA:
return WIFI_DRIVER_FW_PATH_STA;
case WIFI_GET_FW_PATH_AP:
return WIFI_DRIVER_FW_PATH_AP;
case WIFI_GET_FW_PATH_P2P:
return WIFI_DRIVER_FW_PATH_P2P;
}
return NULL;
}
int wifi_change_fw_path(const char *fwpath) {
int len;
int fd;
int ret = 0;
if (!fwpath) return ret;
fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY));
if (fd < 0) {
PLOG(ERROR) << "Failed to open wlan fw path param";
return -1;
}
len = strlen(fwpath) + 1;
if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) {
PLOG(ERROR) << "Failed to write wlan fw path param";
ret = -1;
}
close(fd);
return ret;
}