(一百四十八)Android P wifi启动过程中的sta interface创建

2023-12-19 07:38

本文主要是介绍(一百四十八)Android P wifi启动过程中的sta interface创建,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.启动流程回顾

之前在(一百二十八)Android P WIFI启动流程梳理 梳理了WiFi的启动流程,其中有个环节是和interface创建相关的,扒一下具体流程。

 

2.流程分析

主要看下HalDeviceManager中的相关sta iface创建流程

    /*** Create a STA interface if possible. Changes chip mode and removes conflicting interfaces if* needed and permitted by priority.** @param lowPrioritySta Indicates whether the requested STA is a low priority STA. The priority*                       and preemption rules for low priority STA are:*                       - Do not destroy any interface for it (even another low priority STA)*                       - Destroy it for any other request* @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 handler Handler on which to dispatch listener. Null implies the listener will be*                invoked synchronously from the context of the client which triggered the*                iface destruction.* @return A newly created interface - or null if the interface could not be created.*/public IWifiStaIface createStaIface(boolean lowPrioritySta,@Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler) {return (IWifiStaIface) createIface(IfaceType.STA, lowPrioritySta, destroyedListener,handler);}

这边api描述的很精炼

  • Create a STA interface if possible.
  • Changes chip mode
  • removes conflicting interfaces if needed and permitted by priority.

 

    private IWifiIface createIface(int ifaceType, boolean lowPriority,InterfaceDestroyedListener destroyedListener, Handler handler) {if (mDbg) {Log.d(TAG, "createIface: ifaceType=" + ifaceType + ", lowPriority=" + lowPriority);}synchronized (mLock) {WifiChipInfo[] chipInfos = getAllChipInfo();if (chipInfos == null) {Log.e(TAG, "createIface: no chip info found");stopWifi(); // major error: shutting downreturn null;}if (!validateInterfaceCache(chipInfos)) {Log.e(TAG, "createIface: local cache is invalid!");stopWifi(); // major error: shutting downreturn null;}IWifiIface iface = createIfaceIfPossible(chipInfos, ifaceType, lowPriority,destroyedListener, handler);if (iface != null) { // means that some configuration has changedif (!dispatchAvailableForRequestListeners()) {return null; // catastrophic failure - shut down}}return iface;}}

 

2.1 getAllChipInfo

    /*** Get current information about all the chips in the system: modes, current mode (if any), and* any existing interfaces.** Intended to be called whenever we need to configure the chips - information is NOT cached (to* reduce the likelihood that we get out-of-sync).*/private WifiChipInfo[] getAllChipInfo() {if (VDBG) Log.d(TAG, "getAllChipInfo");synchronized (mLock) {if (mWifi == null) {Log.e(TAG, "getAllChipInfo: called but mWifi is null!?");return null;}try {MutableBoolean statusOk = new MutableBoolean(false);Mutable<ArrayList<Integer>> chipIdsResp = new Mutable<>();// get all chip IDsmWifi.getChipIds((WifiStatus status, ArrayList<Integer> chipIds) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {chipIdsResp.value = chipIds;} else {Log.e(TAG, "getChipIds failed: " + statusString(status));}});if (!statusOk.value) {return null;}if (VDBG) Log.d(TAG, "getChipIds=" + chipIdsResp.value);if (chipIdsResp.value.size() == 0) {Log.e(TAG, "Should have at least 1 chip!");return null;}int chipInfoIndex = 0;WifiChipInfo[] chipsInfo = new WifiChipInfo[chipIdsResp.value.size()];Mutable<IWifiChip> chipResp = new Mutable<>();for (Integer chipId: chipIdsResp.value) {mWifi.getChip(chipId, (WifiStatus status, IWifiChip chip) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {chipResp.value = chip;} else {Log.e(TAG, "getChip failed: " + statusString(status));}});if (!statusOk.value) {return null;}Mutable<ArrayList<IWifiChip.ChipMode>> availableModesResp = new Mutable<>();chipResp.value.getAvailableModes((WifiStatus status, ArrayList<IWifiChip.ChipMode> modes) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {availableModesResp.value = modes;} else {Log.e(TAG, "getAvailableModes failed: " + statusString(status));}});if (!statusOk.value) {return null;}MutableBoolean currentModeValidResp = new MutableBoolean(false);MutableInt currentModeResp = new MutableInt(0);chipResp.value.getMode((WifiStatus status, int modeId) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {currentModeValidResp.value = true;currentModeResp.value = modeId;} else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {statusOk.value = true; // valid response} else {Log.e(TAG, "getMode failed: " + statusString(status));}});if (!statusOk.value) {return null;}Mutable<ArrayList<String>> ifaceNamesResp = new Mutable<>();MutableInt ifaceIndex = new MutableInt(0);chipResp.value.getStaIfaceNames((WifiStatus status, ArrayList<String> ifnames) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {ifaceNamesResp.value = ifnames;} else {Log.e(TAG, "getStaIfaceNames failed: " + statusString(status));}});if (!statusOk.value) {return null;}WifiIfaceInfo[] staIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];for (String ifaceName: ifaceNamesResp.value) {chipResp.value.getStaIface(ifaceName,(WifiStatus status, IWifiStaIface iface) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();ifaceInfo.name = ifaceName;ifaceInfo.iface = iface;staIfaces[ifaceIndex.value++] = ifaceInfo;} else {Log.e(TAG, "getStaIface failed: " + statusString(status));}});if (!statusOk.value) {return null;}}ifaceIndex.value = 0;chipResp.value.getApIfaceNames((WifiStatus status, ArrayList<String> ifnames) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {ifaceNamesResp.value = ifnames;} else {Log.e(TAG, "getApIfaceNames failed: " + statusString(status));}});if (!statusOk.value) {return null;}WifiIfaceInfo[] apIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];for (String ifaceName: ifaceNamesResp.value) {chipResp.value.getApIface(ifaceName,(WifiStatus status, IWifiApIface iface) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();ifaceInfo.name = ifaceName;ifaceInfo.iface = iface;apIfaces[ifaceIndex.value++] = ifaceInfo;} else {Log.e(TAG, "getApIface failed: " + statusString(status));}});if (!statusOk.value) {return null;}}ifaceIndex.value = 0;chipResp.value.getP2pIfaceNames((WifiStatus status, ArrayList<String> ifnames) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {ifaceNamesResp.value = ifnames;} else {Log.e(TAG, "getP2pIfaceNames failed: " + statusString(status));}});if (!statusOk.value) {return null;}WifiIfaceInfo[] p2pIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];for (String ifaceName: ifaceNamesResp.value) {chipResp.value.getP2pIface(ifaceName,(WifiStatus status, IWifiP2pIface iface) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();ifaceInfo.name = ifaceName;ifaceInfo.iface = iface;p2pIfaces[ifaceIndex.value++] = ifaceInfo;} else {Log.e(TAG, "getP2pIface failed: " + statusString(status));}});if (!statusOk.value) {return null;}}ifaceIndex.value = 0;chipResp.value.getNanIfaceNames((WifiStatus status, ArrayList<String> ifnames) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {ifaceNamesResp.value = ifnames;} else {Log.e(TAG, "getNanIfaceNames failed: " + statusString(status));}});if (!statusOk.value) {return null;}WifiIfaceInfo[] nanIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];for (String ifaceName: ifaceNamesResp.value) {chipResp.value.getNanIface(ifaceName,(WifiStatus status, IWifiNanIface iface) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();ifaceInfo.name = ifaceName;ifaceInfo.iface = iface;nanIfaces[ifaceIndex.value++] = ifaceInfo;} else {Log.e(TAG, "getNanIface failed: " + statusString(status));}});if (!statusOk.value) {return null;}}WifiChipInfo chipInfo = new WifiChipInfo();chipsInfo[chipInfoIndex++] = chipInfo;chipInfo.chip = chipResp.value;chipInfo.chipId = chipId;chipInfo.availableModes = availableModesResp.value;chipInfo.currentModeIdValid = currentModeValidResp.value;chipInfo.currentModeId = currentModeResp.value;chipInfo.ifaces[IfaceType.STA] = staIfaces;chipInfo.ifaces[IfaceType.AP] = apIfaces;chipInfo.ifaces[IfaceType.P2P] = p2pIfaces;chipInfo.ifaces[IfaceType.NAN] = nanIfaces;}return chipsInfo;} catch (RemoteException e) {Log.e(TAG, "getAllChipInfoAndValidateCache exception: " + e);}}return null;}

顾名思义,获取芯片相关信息

                    WifiChipInfo chipInfo = new WifiChipInfo();chipsInfo[chipInfoIndex++] = chipInfo;chipInfo.chip = chipResp.value;chipInfo.chipId = chipId;chipInfo.availableModes = availableModesResp.value;chipInfo.currentModeIdValid = currentModeValidResp.value;chipInfo.currentModeId = currentModeResp.value;chipInfo.ifaces[IfaceType.STA] = staIfaces;chipInfo.ifaces[IfaceType.AP] = apIfaces;chipInfo.ifaces[IfaceType.P2P] = p2pIfaces;chipInfo.ifaces[IfaceType.NAN] = nanIfaces;

可以先看最后,将从底层获取上来的信息封装成了一个java对象,WifiChipInfo.

那在往上看下WifiChipInfo 各个参数是如何获取的

http://androidxref.com/9.0.0_r3/xref/hardware/interfaces/wifi/1.0/IWifiChip.hal#108

/*** Interface that represents a chip that must be configured as a single unit.* The HAL/driver/firmware will be responsible for determining which phy is used* to perform operations like NAN, RTT, etc.*/
interface IWifiChip {/*** Set of interface types with the maximum number of interfaces that can have* one of the specified type for a given ChipIfaceCombination. See* ChipIfaceCombination for examples.*/struct ChipIfaceCombinationLimit {vec<IfaceType> types; // Each IfaceType must occur at most once.uint32_t maxIfaces;};/*** Set of interfaces that can operate concurrently when in a given mode. See* ChipMode below.** For example:*   [{STA} <= 2]*       At most two STA interfaces are supported*       [], [STA], [STA+STA]**   [{STA} <= 1, {NAN} <= 1, {AP} <= 1]*       Any combination of STA, NAN, AP*       [], [STA], [NAN], [AP], [STA+NAN], [STA+AP], [NAN+AP], [STA+NAN+AP]**   [{STA} <= 1, {NAN,P2P} <= 1]*       Optionally a STA and either NAN or P2P*       [], [STA], [STA+NAN], [STA+P2P], [NAN], [P2P]*       Not included [NAN+P2P], [STA+NAN+P2P]**   [{STA} <= 1, {STA,NAN} <= 1]*       Optionally a STA and either a second STA or a NAN*       [], [STA], [STA+NAN], [STA+STA], [NAN]*       Not included [STA+STA+NAN]*/struct ChipIfaceCombination {vec<ChipIfaceCombinationLimit> limits;};/*** A mode that the chip can be put in. A mode defines a set of constraints on* the interfaces that can exist while in that mode. Modes define a unit of* configuration where all interfaces must be torn down to switch to a* different mode. Some HALs may only have a single mode, but an example where* multiple modes would be required is if a chip has different firmwares with* different capabilities.** When in a mode, it must be possible to perform any combination of creating* and removing interfaces as long as at least one of the* ChipIfaceCombinations is satisfied. This means that if a chip has two* available combinations, [{STA} <= 1] and [{AP} <= 1] then it is expected* that exactly one STA interface or one AP interface can be created, but it* is not expected that both a STA and AP interface could be created. If it* was then there would be a single available combination* [{STA} <=1, {AP} <= 1].** When switching between two available combinations it is expected that* interfaces only supported by the initial combination must be removed until* the target combination is also satisfied. At that point new interfaces* satisfying only the target combination can be added (meaning the initial* combination limits will no longer satisfied). The addition of these new* interfaces must not impact the existence of interfaces that satisfy both* combinations.** For example, a chip with available combinations:*     [{STA} <= 2, {NAN} <=1] and [{STA} <=1, {NAN} <= 1, {AP} <= 1}]* If the chip currently has 3 interfaces STA, STA and NAN and wants to add an* AP interface in place of one of the STAs then first one of the STA* interfaces must be removed and then the AP interface can be created after* the STA had been torn down. During this process the remaining STA and NAN* interfaces must not be removed/recreated.** If a chip does not support this kind of reconfiguration in this mode then* the combinations must be separated into two separate modes. Before* switching modes all interfaces must be torn down, the mode switch must be* enacted and when it completes the new interfaces must be brought up.*/struct ChipMode {/*** Id that can be used to put the chip in this mode.*/ChipModeId id;/*** A list of the possible interface combinations that the chip can have* while in this mode.*/vec<ChipIfaceCombination> availableCombinations;};

 

 

2.1.1 chipIDs

                MutableBoolean statusOk = new MutableBoolean(false);Mutable<ArrayList<Integer>> chipIdsResp = new Mutable<>();// get all chip IDsmWifi.getChipIds((WifiStatus status, ArrayList<Integer> chipIds) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {chipIdsResp.value = chipIds;} else {Log.e(TAG, "getChipIds failed: " + statusString(status));}});

PS:Mutable是可变的意思,https://blog.csdn.net/rentee/article/details/82999955 中有讲,后续再看下

 

hardware/interfaces/wifi/1.2/default/wifi.cpp

Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) {return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,&Wifi::getChipIdsInternal, hidl_status_cb);
}std::pair<WifiStatus, std::vector<ChipId>> Wifi::getChipIdsInternal() {std::vector<ChipId> chip_ids;if (chip_.get()) {chip_ids.emplace_back(kChipId);}return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)};
}namespace {
// Chip ID to use for the only supported chip.
static constexpr android::hardware::wifi::V1_0::ChipId kChipId = 0;
}  // namespace

从代码来看Android原生默认芯片个数为1,id = 0

 

2.1.2 chip

Mutable<IWifiChip> chipResp = new Mutable<>();for (Integer chipId: chipIdsResp.value) {mWifi.getChip(chipId, (WifiStatus status, IWifiChip chip) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {chipResp.value = chip;} else {Log.e(TAG, "getChip failed: " + statusString(status));}});if (!statusOk.value) {return null;}

hardware/interfaces/wifi/1.2/default/wifi.cpp

Return<void> Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) {return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,&Wifi::getChipInternal, hidl_status_cb, chip_id);
}std::pair<WifiStatus, sp<IWifiChip>> Wifi::getChipInternal(ChipId chip_id) {if (!chip_.get()) {return {createWifiStatus(WifiStatusCode::ERROR_NOT_STARTED), nullptr};}if (chip_id != kChipId) {return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};}return {createWifiStatus(WifiStatusCode::SUCCESS), chip_};
}

而chip_是之前加载驱动成功后初始化起来的,如注释所示: // Create the chip instance once the HAL is started.

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 = initializeModeControllerAndLegacyHal();if (wifi_status.code == WifiStatusCode::SUCCESS) {// Create the chip instance once the HAL is started.chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,feature_flags_);run_state_ = RunState::STARTED;for (const auto& callback : event_cb_handler_.getCallbacks()) {if (!callback->onStart().isOk()) {LOG(ERROR) << "Failed to invoke onStart callback";};}LOG(INFO) << "Wifi HAL started";} 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;
}

 

2.1.3 AvailableModes

                    Mutable<ArrayList<IWifiChip.ChipMode>> availableModesResp = new Mutable<>();chipResp.value.getAvailableModes((WifiStatus status, ArrayList<IWifiChip.ChipMode> modes) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {availableModesResp.value = modes;} else {Log.e(TAG, "getAvailableModes failed: " + statusString(status));}});

hardware/interfaces/wifi/1.2/default/wifi_chip.cpp

Return<void> WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) {return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,&WifiChip::getAvailableModesInternal,hidl_status_cb);
}std::pair<WifiStatus, std::vector<IWifiChip::ChipMode>>
WifiChip::getAvailableModesInternal() {return {createWifiStatus(WifiStatusCode::SUCCESS), modes_};
}

再看下modes_是在哪里初始化的

void WifiChip::populateModes() {// The chip combination supported for current devices is fixed.// They can be one of the following based on device features:// a) 2 separate modes of operation with 1 interface combination each://    Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN(optional)//                       concurrent iface operations.//    Mode 2 (AP mode): Will support 1 AP iface operation.//// b) 1 mode of operation with 2 interface combinations// (conditional on isDualInterfaceSupported())://    Interface Combination 1: Will support 1 STA and 1 P2P or NAN(optional)//                             concurrent iface operations.//    Interface Combination 2: Will support 1 STA and 1 AP concurrent//                             iface operations.// If Aware is enabled (conditional on isAwareSupported()), the iface// combination will be modified to support either P2P or NAN in place of// just P2P.if (feature_flags_.lock()->isDualInterfaceSupported()) {// V2 Iface combinations for Mode Id = 2.const IWifiChip::ChipIfaceCombinationLimitchip_iface_combination_limit_1 = {{IfaceType::STA}, 1};const IWifiChip::ChipIfaceCombinationLimitchip_iface_combination_limit_2 = {{IfaceType::AP}, 1};IWifiChip::ChipIfaceCombinationLimit chip_iface_combination_limit_3;if (feature_flags_.lock()->isAwareSupported()) {chip_iface_combination_limit_3 = {{IfaceType::P2P, IfaceType::NAN},1};} else {chip_iface_combination_limit_3 = {{IfaceType::P2P}, 1};}const IWifiChip::ChipIfaceCombination chip_iface_combination_1 = {{chip_iface_combination_limit_1, chip_iface_combination_limit_2}};const IWifiChip::ChipIfaceCombination chip_iface_combination_2 = {{chip_iface_combination_limit_1, chip_iface_combination_limit_3}};if (feature_flags_.lock()->isApDisabled()) {const IWifiChip::ChipMode chip_mode = {kV2ChipModeId,{chip_iface_combination_2}};modes_ = {chip_mode};} else {const IWifiChip::ChipMode chip_mode = {kV2ChipModeId,{chip_iface_combination_1, chip_iface_combination_2}};modes_ = {chip_mode};}} else {// V1 Iface combinations for Mode Id = 0. (STA Mode)const IWifiChip::ChipIfaceCombinationLimitsta_chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};IWifiChip::ChipIfaceCombinationLimit sta_chip_iface_combination_limit_2;if (feature_flags_.lock()->isAwareSupported()) {sta_chip_iface_combination_limit_2 = {{IfaceType::P2P, IfaceType::NAN}, 1};} else {sta_chip_iface_combination_limit_2 = {{IfaceType::P2P}, 1};}const IWifiChip::ChipIfaceCombination sta_chip_iface_combination = {{sta_chip_iface_combination_limit_1,sta_chip_iface_combination_limit_2}};const IWifiChip::ChipMode sta_chip_mode = {kV1StaChipModeId, {sta_chip_iface_combination}};// Iface combinations for Mode Id = 1. (AP Mode)const IWifiChip::ChipIfaceCombinationLimitap_chip_iface_combination_limit = {{IfaceType::AP}, 1};const IWifiChip::ChipIfaceCombination ap_chip_iface_combination = {{ap_chip_iface_combination_limit}};const IWifiChip::ChipMode ap_chip_mode = {kV1ApChipModeId,{ap_chip_iface_combination}};if (feature_flags_.lock()->isApDisabled()) {modes_ = {sta_chip_mode};} else {modes_ = {sta_chip_mode, ap_chip_mode};}}
}

支持的模式有讲的清楚,先区分是否支持DualInterface

1)若支持

i 支持ap,则组合模式有sta+p2p 或者sta+ap,标记为kV2ChipModeId

ii 不支持ap,则组合模式有sta + p2p,标记为kV2ChipModeId

2)若不支持

i 支持ap,则组合模式有sta+p2p 或者ap,标记为kV1ApChipModeId

ii 不支持ap,则组合模式有sta + p2p,标记为kV1StaChipModeId

//当前设备支持的芯片组合是固定的。//它们可以是基于设备功能的以下之一:// a)单接口   2种不同的操作模式,每种模式有1个接口组合://模式1(STA模式):支持1个STA和1个P2P或NAN(可选)//并发iface操作。//模式2(AP模式):支持1个AP操作。//// b)双接口 具有2个接口组合的1种操作模式//(以isDualInterfaceSupported()为条件)://接口组合1:支持1个STA和1个P2P或NAN(可选)//并发iface操作。//接口组合2:将支持1个STA和1个AP并发// iface运营//如果启用了Aware(以isAwareSupported()为条件),则为iface//将修改组合以支持P2P或NAN代替//只是P2P。// These mode ID's should be unique (even across combo versions). Refer to
// handleChipConfiguration() for it's usage.
// Mode ID's for V1
constexpr ChipModeId kV1StaChipModeId = 0;
constexpr ChipModeId kV1ApChipModeId = 1;
// Mode ID for V2
constexpr ChipModeId kV2ChipModeId = 2;

 

2.1.4 currentModeValid & currentMode

                    MutableBoolean currentModeValidResp = new MutableBoolean(false);MutableInt currentModeResp = new MutableInt(0);chipResp.value.getMode((WifiStatus status, int modeId) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {currentModeValidResp.value = true;currentModeResp.value = modeId;} else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {statusOk.value = true; // valid response} else {Log.e(TAG, "getMode failed: " + statusString(status));}});

hardware/interfaces/wifi/1.2/default/wifi_chip.cpp

Return<void> WifiChip::getMode(getMode_cb hidl_status_cb) {return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,&WifiChip::getModeInternal, hidl_status_cb);
}std::pair<WifiStatus, uint32_t> WifiChip::getModeInternal() {if (!isValidModeId(current_mode_id_)) {return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE),current_mode_id_};}return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_};
}

看下current_mode_id_是何时初始化的

WifiStatus WifiChip::configureChipInternal(/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,ChipModeId mode_id) {if (!isValidModeId(mode_id)) {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(lock, 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;LOG(INFO) << "Configured chip in mode " << mode_id;return status;
}

configureChipInternal是后续创建sta iface的时候配置的,初始的时候应该是

current_mode_id_(kInvalidModeId)

 

2.1.5 staIfaceNames & staIface

                    Mutable<ArrayList<String>> ifaceNamesResp = new Mutable<>();MutableInt ifaceIndex = new MutableInt(0);chipResp.value.getStaIfaceNames((WifiStatus status, ArrayList<String> ifnames) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {ifaceNamesResp.value = ifnames;} else {Log.e(TAG, "getStaIfaceNames failed: " + statusString(status));}});if (!statusOk.value) {return null;}WifiIfaceInfo[] staIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];for (String ifaceName: ifaceNamesResp.value) {chipResp.value.getStaIface(ifaceName,(WifiStatus status, IWifiStaIface iface) -> {statusOk.value = status.code == WifiStatusCode.SUCCESS;if (statusOk.value) {WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();ifaceInfo.name = ifaceName;ifaceInfo.iface = iface;staIfaces[ifaceIndex.value++] = ifaceInfo;} else {Log.e(TAG, "getStaIface failed: " + statusString(status));}});if (!statusOk.value) {return null;}}

hardware/interfaces/wifi/1.2/default/wifi_chip.cpp

Return<void> WifiChip::getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) {return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,&WifiChip::getStaIfaceNamesInternal, hidl_status_cb);
}std::pair<WifiStatus, std::vector<hidl_string>>
WifiChip::getStaIfaceNamesInternal() {if (sta_ifaces_.empty()) {return {createWifiStatus(WifiStatusCode::SUCCESS), {}};}return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)};
}std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};}std::string ifname = allocateApOrStaIfaceName();sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_);sta_ifaces_.push_back(iface);for (const auto& callback : event_cb_handler_.getCallbacks()) {if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {LOG(ERROR) << "Failed to invoke onIfaceAdded callback";}}return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
}// Return "wlan0", if "wlan0" is not already in use, else return "wlan1".
// This is based on the assumption that we'll have a max of 2 concurrent
// AP/STA ifaces.
std::string WifiChip::allocateApOrStaIfaceName() {auto ap_iface = findUsingName(ap_ifaces_, getWlan0IfaceName());auto sta_iface = findUsingName(sta_ifaces_, getWlan0IfaceName());if (!ap_iface.get() && !sta_iface.get()) {return getWlan0IfaceName();}ap_iface = findUsingName(ap_ifaces_, getWlan1IfaceName());sta_iface = findUsingName(sta_ifaces_, getWlan1IfaceName());if (!ap_iface.get() && !sta_iface.get()) {return getWlan1IfaceName();}// This should never happen. We screwed up somewhere if it did.CHECK(0) << "wlan0 and wlan1 in use already!";return {};
}

可以看到如果wlan0没有用就返回wlan0,否则返回wlan1,否则返回空

 

 

Return<void> WifiChip::getStaIface(const hidl_string& ifname,getStaIface_cb hidl_status_cb) {return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,&WifiChip::getStaIfaceInternal, hidl_status_cb,ifname);
}std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::getStaIfaceInternal(const std::string& ifname) {const auto iface = findUsingName(sta_ifaces_, ifname);if (!iface.get()) {return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};}return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
}template <typename Iface>
sp<Iface> findUsingName(std::vector<sp<Iface>>& ifaces,const std::string& name) {std::vector<hidl_string> names;for (const auto& iface : ifaces) {if (name == iface->getName()) {return iface;}}return nullptr;
}

用刚才的获取到的接口名称来获取对应的iface

 

2.2 createIfaceIfPossible

    private IWifiIface createIfaceIfPossible(WifiChipInfo[] chipInfos, int ifaceType,boolean lowPriority, InterfaceDestroyedListener destroyedListener, Handler handler) {if (VDBG) {Log.d(TAG, "createIfaceIfPossible: chipInfos=" + Arrays.deepToString(chipInfos)+ ", ifaceType=" + ifaceType + ", lowPriority=" + lowPriority);}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 (VDBG) {Log.d(TAG, chipIfaceCombo + " expands to "+ Arrays.deepToString(expandedIfaceCombos));}for (int[] expandedIfaceCombo: expandedIfaceCombos) {IfaceCreationData currentProposal = canIfaceComboSupportRequest(chipInfo, chipMode, expandedIfaceCombo, ifaceType, lowPriority);if (compareIfaceCreationData(currentProposal,bestIfaceCreationProposal)) {if (VDBG) 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(cacheEntry.name, destroyedListener, handler));}cacheEntry.creationTime = mClock.getUptimeSinceBootMillis();cacheEntry.isLowPriority = lowPriority;if (mDbg) Log.d(TAG, "createIfaceIfPossible: added cacheEntry=" + cacheEntry);mInterfaceInfoCache.put(Pair.create(cacheEntry.name, cacheEntry.type), cacheEntry);return iface;}}}return null;}

遍历所有的组合找到最适合的,关键api

  • expandIfaceCombos
  • canIfaceComboSupportRequest
  • compareIfaceCreationData
        synchronized (mLock) {IfaceCreationData bestIfaceCreationProposal = null;for (WifiChipInfo chipInfo: chipInfos) {
//暂时只有一个芯片信息for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) {
//对应于
支持的模式有讲的清楚,先区分是否支持DualInterface1)若支持i 支持ap,则模式单一,组合有2种,为sta+p2p 或者sta+ap,标记为kV2ChipModeIdii 不支持ap,则模式单一,组合有1种,为sta + p2p,标记为kV2ChipModeId2)若不支持i 支持ap,则模式有sta+p2p 或者ap,标记为kV1ApChipModeIdii 不支持ap,则模式单一,为sta+p2p,标记为kV1StaChipModeIdfor (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode.availableCombinations) {
对应不同的模式有不同的combinationsint[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo);if (VDBG) {Log.d(TAG, chipIfaceCombo + " expands to "+ Arrays.deepToString(expandedIfaceCombos));}for (int[] expandedIfaceCombo: expandedIfaceCombos) {IfaceCreationData currentProposal = canIfaceComboSupportRequest(chipInfo, chipMode, expandedIfaceCombo, ifaceType, lowPriority);if (compareIfaceCreationData(currentProposal,bestIfaceCreationProposal)) {if (VDBG) Log.d(TAG, "new proposal accepted");bestIfaceCreationProposal = currentProposal;}}}}}

 

2.2.1 expandIfaceCombos

    /*** Expands (or provides an alternative representation) of the ChipIfaceCombination as all* possible combinations of interface.** Returns [# of combinations][4 (IfaceType)]** Note: there could be duplicates - allow (inefficient but ...).* TODO: optimize by using a Set as opposed to a []: will remove duplicates. Will need to* provide correct hashes.*/private int[][] expandIfaceCombos(IWifiChip.ChipIfaceCombination chipIfaceCombo) {int numOfCombos = 1;for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) {for (int i = 0; i < limit.maxIfaces; ++i) {numOfCombos *= limit.types.size();}}int[][] expandedIfaceCombos = new int[numOfCombos][IFACE_TYPES_BY_PRIORITY.length];int span = numOfCombos; // span of an individual type (or sub-tree size)for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) {for (int i = 0; i < limit.maxIfaces; ++i) {span /= limit.types.size();for (int k = 0; k < numOfCombos; ++k) {expandedIfaceCombos[k][limit.types.get((k / span) % limit.types.size())]++;}}}return expandedIfaceCombos;}

随便看个iface combination

        const IWifiChip::ChipIfaceCombinationLimit
            chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
        const IWifiChip::ChipIfaceCombinationLimit
            chip_iface_combination_limit_2 = {{IfaceType::AP}, 1};
        const IWifiChip::ChipIfaceCombination chip_iface_combination_1 = {
            {chip_iface_combination_limit_1, chip_iface_combination_limit_2}};

http://androidxref.com/9.0.0_r3/xref/hardware/interfaces/wifi/1.0/IWifiChip.hal#108

  /*** Set of interface types with the maximum number of interfaces that can have* one of the specified type for a given ChipIfaceCombination. See* ChipIfaceCombination for examples.*/struct ChipIfaceCombinationLimit {vec<IfaceType> types; // Each IfaceType must occur at most once.uint32_t maxIfaces;};

假定iface combination 为 STA + AP,带入debug

    /*** Expands (or provides an alternative representation) of the ChipIfaceCombination as all* possible combinations of interface.** Returns [# of combinations][4 (IfaceType)]** Note: there could be duplicates - allow (inefficient but ...).* TODO: optimize by using a Set as opposed to a []: will remove duplicates. Will need to* provide correct hashes.*/private int[][] expandIfaceCombos(IWifiChip.ChipIfaceCombination chipIfaceCombo) {int numOfCombos = 1;for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) {for (int i = 0; i < limit.maxIfaces; ++i) {numOfCombos *= limit.types.size();
//计算双接口的组合个数 numOfCombos = 1}}int[][] expandedIfaceCombos = new int[numOfCombos][IFACE_TYPES_BY_PRIORITY.length];
//拼接成一个二维数组,行为numOfCombos,1 ,列为4,ap+sta+p2p+NAN
//    /* This "PRIORITY" is not for deciding interface elimination (that is controlled by* allowedToDeleteIfaceTypeForRequestedType. This priority is used for:* - Comparing 2 configuration options* - Order of dispatch of available for request listeners*/private static final int[] IFACE_TYPES_BY_PRIORITY ={IfaceType.AP, IfaceType.STA, IfaceType.P2P, IfaceType.NAN};
//int span = numOfCombos; // span of an individual type (or sub-tree size)
//span = 1for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) {for (int i = 0; i < limit.maxIfaces; ++i) {span /= limit.types.size();
//span = 1;for (int k = 0; k < numOfCombos; ++k) {expandedIfaceCombos[k][limit.types.get((k / span) % limit.types.size())]++;}}}return expandedIfaceCombos;}

对于numofCombos的计算参考,比如

  /*** Set of interfaces that can operate concurrently when in a given mode. See* ChipMode below.** For example:*   [{STA} <= 2]*       At most two STA interfaces are supported*       [], [STA], [STA+STA]
numofCombos=1**   [{STA} <= 1, {NAN} <= 1, {AP} <= 1]*       Any combination of STA, NAN, AP*       [], [STA], [NAN], [AP], [STA+NAN], [STA+AP], [NAN+AP], [STA+NAN+AP]*
numofCombos=1*   [{STA} <= 1, {NAN,P2P} <= 1]*       Optionally a STA and either NAN or P2P*       [], [STA], [STA+NAN], [STA+P2P], [NAN], [P2P]*       Not included [NAN+P2P], [STA+NAN+P2P]*
numofCombos=2*   [{STA} <= 1, {STA,NAN} <= 1]*       Optionally a STA and either a second STA or a NAN*       [], [STA], [STA+NAN], [STA+STA], [NAN]*       Not included [STA+STA+NAN]*/
numofCombos=2struct ChipIfaceCombination {vec<ChipIfaceCombinationLimit> limits;};

画一个二维数组

numofCombos\IFACE_TYPES_BY_PRIORITY0123
01100

懵逼了,vec是个矢量,get的确实是int值,准确说来是枚举值

/*** List of Iface types supported.*/
enum IfaceType : uint32_t {STA,AP,P2P,/*** NAN control interface. Datapath support must be queried and created* through this interface.*/NAN,
};

最后得到的二位数组是【1,1,0,0】表示啥呢。。。

在举个例子

   *   [{STA} <= 1, {NAN,P2P} <= 1]
   *       Optionally a STA and either NAN or P2P
   *       [], [STA], [STA+NAN], [STA+P2P], [NAN], [P2P]
   *       Not included [NAN+P2P], [STA+NAN+P2P]
   *
numofCombos=2

numofCombos\IFACE_TYPES_BY_PRIORITY0123
01  1
11 1 

        for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) {
            for (int i = 0; i < limit.maxIfaces; ++i) {
                span /= limit.types.size(); 1
                for (int k = 0; k < numOfCombos; ++k) {
                    expandedIfaceCombos[k][limit.types.get((k / span) % limit.types.size())]++;
                }
            }
        }

虽然算法不是很理解,但是从表来看是将combo用二维数组表示了下。待续。。。

 

2.2.2 canIfaceComboSupportRequest

    /*** Checks whether the input chip-iface-combo can support the requested interface type: if not* then returns null, if yes then returns information containing the list of interfaces which* would have to be removed first before the requested interface can be created.** Note: the list of interfaces to be removed is EMPTY if a chip mode change is required - in* that case ALL the interfaces on the current chip have to be removed first.** Response determined based on:* - Mode configuration: i.e. could the mode support the interface type in principle* - Priority information: i.e. are we 'allowed' to remove interfaces in order to create the*   requested interface*/private IfaceCreationData canIfaceComboSupportRequest(WifiChipInfo chipInfo,IWifiChip.ChipMode chipMode, int[] chipIfaceCombo, int ifaceType, boolean lowPriority) {if (VDBG) {Log.d(TAG, "canIfaceComboSupportRequest: chipInfo=" + chipInfo + ", chipMode="+ chipMode + ", chipIfaceCombo=" + chipIfaceCombo + ", ifaceType=" + ifaceType+ ", lowPriority=" + lowPriority);}// short-circuit: does the chipIfaceCombo even support the requested type?if (chipIfaceCombo[ifaceType] == 0) {if (VDBG) Log.d(TAG, "Requested type not supported by combo");return null;}boolean isChipModeChangeProposed =chipInfo.currentModeIdValid && chipInfo.currentModeId != chipMode.id;// short-circuit: can't change chip-mode if an existing interface on this chip has a higher// priority than the requested interfaceif (isChipModeChangeProposed) {for (int type: IFACE_TYPES_BY_PRIORITY) {if (chipInfo.ifaces[type].length != 0) {if (lowPriority) {if (VDBG) {Log.d(TAG, "Couldn't delete existing type " + type+ " interfaces for a low priority request");}return null;}if (!allowedToDeleteIfaceTypeForRequestedType(type, ifaceType,chipInfo.ifaces, chipInfo.ifaces[type].length)) {if (VDBG) {Log.d(TAG, "Couldn't delete existing type " + type+ " interfaces for requested type");}return null;}}}// but if priority allows the mode change then we're good to goIfaceCreationData ifaceCreationData = new IfaceCreationData();ifaceCreationData.chipInfo = chipInfo;ifaceCreationData.chipModeId = chipMode.id;return ifaceCreationData;}// possibly supportedList<WifiIfaceInfo> interfacesToBeRemovedFirst = new ArrayList<>();for (int type: IFACE_TYPES_BY_PRIORITY) {int tooManyInterfaces = chipInfo.ifaces[type].length - chipIfaceCombo[type];// need to count the requested interface as wellif (type == ifaceType) {tooManyInterfaces += 1;}if (tooManyInterfaces > 0) { // may need to delete someif (lowPriority) {if (VDBG) {Log.d(TAG, "Couldn't delete existing type " + type+ " interfaces for a low priority request");}return null;}if (!allowedToDeleteIfaceTypeForRequestedType(type, ifaceType, chipInfo.ifaces,tooManyInterfaces)) {if (VDBG) {Log.d(TAG, "Would need to delete some higher priority interfaces");}return null;}// delete the most recently created interfaces or LOW priority interfacesinterfacesToBeRemovedFirst = selectInterfacesToDelete(tooManyInterfaces,chipInfo.ifaces[type]);}}IfaceCreationData ifaceCreationData = new IfaceCreationData();ifaceCreationData.chipInfo = chipInfo;ifaceCreationData.chipModeId = chipMode.id;ifaceCreationData.interfacesToBeRemovedFirst = interfacesToBeRemovedFirst;return ifaceCreationData;}

    /**
     * Checks whether the input chip-iface-combo can support the requested interface type: if not
     * then returns null, if yes then returns information containing the list of interfaces which
     * would have to be removed first before the requested interface can be created.
     *
     * Note: the list of interfaces to be removed is EMPTY if a chip mode change is required - in
     * that case ALL the interfaces on the current chip have to be removed first.
     *
     * Response determined based on:
     * - Mode configuration: i.e. could the mode support the interface type in principle
     * - Priority information: i.e. are we 'allowed' to remove interfaces in order to create the
     *   requested interface
     */

讲的很明白了,看下当前combo是否支持请求创建的interface type,如果不可以支持返回null,否则返回要移除挪位置的接口。移除由两个因素决定,mode configuration和priority,更详细的rule如下

    /*** Returns true if we're allowed to delete the existing interface type for the requested* interface type.** Rules - applies in order:** General rules:* 1. No interface will be destroyed for a requested interface of the same type* 2. No interface will be destroyed if one of the requested interfaces already exists* 3. If there are >1 interface of an existing type, then it is ok to destroy that type*    interface** Type-specific rules (but note that the general rules are appied first):* 4. Request for AP or STA will destroy any other interface* 5. Request for P2P will destroy NAN-only (but will destroy a second STA per #3)* 6. Request for NAN will not destroy any interface (but will destroy a second STA per #3)** Note: the 'numNecessaryInterfaces' is used to specify how many interfaces would be needed to* be deleted. This is used to determine whether there are that many low priority interfaces* of the requested type to delete.*/private boolean allowedToDeleteIfaceTypeForRequestedType(int existingIfaceType,int requestedIfaceType, WifiIfaceInfo[][] currentIfaces, int numNecessaryInterfaces) {// rule 0: check for any low priority interfacesint numAvailableLowPriorityInterfaces = 0;for (InterfaceCacheEntry entry : mInterfaceInfoCache.values()) {if (entry.type == existingIfaceType && entry.isLowPriority) {numAvailableLowPriorityInterfaces++;}}if (numAvailableLowPriorityInterfaces >= numNecessaryInterfaces) {return true;}// rule 1if (existingIfaceType == requestedIfaceType) {return false;}// rule 2if (currentIfaces[requestedIfaceType].length != 0) {return false;}// rule 3if (currentIfaces[existingIfaceType].length > 1) {return true;}// rule 6if (requestedIfaceType == IfaceType.NAN) {return false;}// rule 5if (requestedIfaceType == IfaceType.P2P) {return existingIfaceType == IfaceType.NAN;}// rule 4, the requestIfaceType is either AP or STAreturn true;}

 

2.2.3 compareIfaceCreationData

    /*** Compares two options to create an interface and determines which is the 'best'. Returns* true if proposal 1 (val1) is better, other false.** Note: both proposals are 'acceptable' bases on priority criteria.** Criteria:* - Proposal is better if it means removing fewer high priority interfaces*/private boolean compareIfaceCreationData(IfaceCreationData val1, IfaceCreationData val2) {if (VDBG) Log.d(TAG, "compareIfaceCreationData: val1=" + val1 + ", val2=" + val2);// deal with trivial case of one or the other being nullif (val1 == null) {return false;} else if (val2 == null) {return true;}for (int type: IFACE_TYPES_BY_PRIORITY) {// # of interfaces to be deleted: the list or all interfaces of the type if mode changeint numIfacesToDelete1 = 0;if (val1.chipInfo.currentModeIdValid&& val1.chipInfo.currentModeId != val1.chipModeId) {numIfacesToDelete1 = val1.chipInfo.ifaces[type].length;} else {numIfacesToDelete1 = val1.interfacesToBeRemovedFirst.size();}int numIfacesToDelete2 = 0;if (val2.chipInfo.currentModeIdValid&& val2.chipInfo.currentModeId != val2.chipModeId) {numIfacesToDelete2 = val2.chipInfo.ifaces[type].length;} else {numIfacesToDelete2 = val2.interfacesToBeRemovedFirst.size();}if (numIfacesToDelete1 < numIfacesToDelete2) {if (VDBG) {Log.d(TAG, "decision based on type=" + type + ": " + numIfacesToDelete1+ " < " + numIfacesToDelete2);}return true;}}// arbitrary - flip a coinif (VDBG) Log.d(TAG, "proposals identical - flip a coin");return false;}

比较待选选项,移除较少的接口的方案优先。

 

2.3 executeChipReconfiguration

    /*** 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 (mDbg) {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 (mDbg) Log.d(TAG, "isModeConfigNeeded=" + isModeConfigNeeded);// first delete interfaces/change modesif (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 doesfor (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 listfor (WifiIfaceInfo ifaceInfo: ifaceCreationData.interfacesToBeRemovedFirst) {removeIfaceInternal(ifaceInfo.iface); // ignore return value}}// create new interfaceMutable<WifiStatus> statusResp = new Mutable<>();Mutable<IWifiIface> ifaceResp = new Mutable<>();switch (ifaceType) {case IfaceType.STA:ifaceCreationData.chipInfo.chip.createStaIface((WifiStatus status, IWifiStaIface iface) -> {statusResp.value = status;ifaceResp.value = iface;});break;

hardware/interfaces/wifi/1.2/default/wifi_chip.cpp

Return<void> WifiChip::configureChip(ChipModeId mode_id,configureChip_cb hidl_status_cb) {return validateAndCallWithLock(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,&WifiChip::configureChipInternal, hidl_status_cb, mode_id);
}WifiStatus WifiChip::configureChipInternal(/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,ChipModeId mode_id) {if (!isValidModeId(mode_id)) {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(lock, 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;LOG(INFO) << "Configured chip in mode " << mode_id;return status;
}WifiStatus WifiChip::handleChipConfiguration(/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,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.if (isValidModeId(current_mode_id_)) {LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_<< " to mode " << mode_id;invalidateAndRemoveAllIfaces();legacy_hal::wifi_error legacy_status =legacy_hal_.lock()->stop(lock, []() {});if (legacy_status != legacy_hal::WIFI_SUCCESS) {LOG(ERROR) << "Failed to stop legacy HAL: "<< legacyErrorToString(legacy_status);return createWifiStatusFromLegacyError(legacy_status);}}// Firmware mode change not needed for V2 devices.bool success = true;if (mode_id == kV1StaChipModeId) {success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);} else if (mode_id == kV1ApChipModeId) {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);}// Every time the HAL is restarted, we need to register the// radio mode change callback.WifiStatus status = registerRadioModeChangeCallback();if (status.code != WifiStatusCode::SUCCESS) {// This probably is not a critical failure?LOG(ERROR) << "Failed to register radio mode change callback";}return createWifiStatus(WifiStatusCode::SUCCESS);
}

根据chipmode修改chip config,其中

// Firmware mode change not needed for V2 devices.

  • kV1StaChipModeId Firmware 切换为sta模式
  • kV1ApChipModeId Firmware 切换为ap模式

 

Return<void> WifiChip::createStaIface(createStaIface_cb hidl_status_cb) {return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,&WifiChip::createStaIfaceInternal, hidl_status_cb);
}std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};}std::string ifname = allocateApOrStaIfaceName();sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_);sta_ifaces_.push_back(iface);for (const auto& callback : event_cb_handler_.getCallbacks()) {if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {LOG(ERROR) << "Failed to invoke onIfaceAdded callback";}}return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
}// Return "wlan0", if "wlan0" is not already in use, else return "wlan1".
// This is based on the assumption that we'll have a max of 2 concurrent
// AP/STA ifaces.
std::string WifiChip::allocateApOrStaIfaceName() {auto ap_iface = findUsingName(ap_ifaces_, getWlan0IfaceName());auto sta_iface = findUsingName(sta_ifaces_, getWlan0IfaceName());if (!ap_iface.get() && !sta_iface.get()) {return getWlan0IfaceName();}ap_iface = findUsingName(ap_ifaces_, getWlan1IfaceName());sta_iface = findUsingName(sta_ifaces_, getWlan1IfaceName());if (!ap_iface.get() && !sta_iface.get()) {return getWlan1IfaceName();}// This should never happen. We screwed up somewhere if it did.CHECK(0) << "wlan0 and wlan1 in use already!";return {};
}

这边简单来看只是初始化了一个WifiStaIface,并没有实际iface的创建,然后有个回调,会调用callback的onIfaceAdded。

iface的创建真正和driver/kernel关联起来是在哪里呢?

            if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) {Log.e(TAG, "Failed to setup iface in wificond on " + iface);teardownInterface(iface.name);mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();return null;}if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {Log.e(TAG, "Failed to setup iface in supplicant on " + iface);teardownInterface(iface.name);mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();return null;}

看起来是下面两步,一个是在wificond,一个是在supplicant中setup iface,待续

 

3.总结

本文主要就根据chip info创建sta iface的流程进行了梳理,说明了一个浅显的道理,上层功能受底层限制或软件受限于硬件。

 

 

这篇关于(一百四十八)Android P wifi启动过程中的sta interface创建的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/511397

相关文章

Window Server创建2台服务器的故障转移群集的图文教程

《WindowServer创建2台服务器的故障转移群集的图文教程》本文主要介绍了在WindowsServer系统上创建一个包含两台成员服务器的故障转移群集,文中通过图文示例介绍的非常详细,对大家的... 目录一、 准备条件二、在ServerB安装故障转移群集三、在ServerC安装故障转移群集,操作与Ser

Window Server2016 AD域的创建的方法步骤

《WindowServer2016AD域的创建的方法步骤》本文主要介绍了WindowServer2016AD域的创建的方法步骤,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、准备条件二、在ServerA服务器中常见AD域管理器:三、创建AD域,域地址为“test.ly”

SpringBoot 整合 Grizzly的过程

《SpringBoot整合Grizzly的过程》Grizzly是一个高性能的、异步的、非阻塞的HTTP服务器框架,它可以与SpringBoot一起提供比传统的Tomcat或Jet... 目录为什么选择 Grizzly?Spring Boot + Grizzly 整合的优势添加依赖自定义 Grizzly 作为

mysql-8.0.30压缩包版安装和配置MySQL环境过程

《mysql-8.0.30压缩包版安装和配置MySQL环境过程》该文章介绍了如何在Windows系统中下载、安装和配置MySQL数据库,包括下载地址、解压文件、创建和配置my.ini文件、设置环境变量... 目录压缩包安装配置下载配置环境变量下载和初始化总结压缩包安装配置下载下载地址:https://d

SpringBoot项目启动后自动加载系统配置的多种实现方式

《SpringBoot项目启动后自动加载系统配置的多种实现方式》:本文主要介绍SpringBoot项目启动后自动加载系统配置的多种实现方式,并通过代码示例讲解的非常详细,对大家的学习或工作有一定的... 目录1. 使用 CommandLineRunner实现方式:2. 使用 ApplicationRunne

Python在固定文件夹批量创建固定后缀的文件(方法详解)

《Python在固定文件夹批量创建固定后缀的文件(方法详解)》文章讲述了如何使用Python批量创建后缀为.md的文件夹,生成100个,代码中需要修改的路径、前缀和后缀名,并提供了注意事项和代码示例,... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果5.

使用IntelliJ IDEA创建简单的Java Web项目完整步骤

《使用IntelliJIDEA创建简单的JavaWeb项目完整步骤》:本文主要介绍如何使用IntelliJIDEA创建一个简单的JavaWeb项目,实现登录、注册和查看用户列表功能,使用Se... 目录前置准备项目功能实现步骤1. 创建项目2. 配置 Tomcat3. 项目文件结构4. 创建数据库和表5.

使用SpringBoot创建一个RESTful API的详细步骤

《使用SpringBoot创建一个RESTfulAPI的详细步骤》使用Java的SpringBoot创建RESTfulAPI可以满足多种开发场景,它提供了快速开发、易于配置、可扩展、可维护的优点,尤... 目录一、创建 Spring Boot 项目二、创建控制器类(Controller Class)三、运行

springboot整合gateway的详细过程

《springboot整合gateway的详细过程》本文介绍了如何配置和使用SpringCloudGateway构建一个API网关,通过实例代码介绍了springboot整合gateway的过程,需要... 目录1. 添加依赖2. 配置网关路由3. 启用Eureka客户端(可选)4. 创建主应用类5. 自定

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如