(五十八)Android O WiFi启动流程梳理续——setupForClientMode

前言:之前在 (四十四)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

 

1. 流程梳理

1.1 WifiNative

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

 

1.2 WifiVendorHal

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方法

 

1.3 HalDeviceManager

1.3.1 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++ 软件包这张图:

(五十八)Android O WiFi启动流程梳理续——setupForClientMode_第1张图片

对应在out目录下生成的:

/out/soong/.intermediates/hardware/interfaces/wifi/1.0/[email protected]_genc++_headers/gen/android/hardware/wifi/1.0

目录结构和之前看到的aidl-cpp有点类似。

之后参考

(五十八)Android O WiFi启动流程梳理续——setupForClientMode_第2张图片

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

 

1.3.2 createStaIface

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

 

1.4 wifi_chip

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

 

1.5 wifi_mode_controller

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

 

1.6 driver_tool

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

 

1.7 wifi_hal_common

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

 

2. 总结

(五十八)Android O WiFi启动流程梳理续——setupForClientMode_第3张图片

你可能感兴趣的:(Wifi)