本文主要是介绍(一百四十八)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_PRIORITY | 0 | 1 | 2 | 3 |
0 | 1 | 1 | 0 | 0 |
懵逼了,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_PRIORITY | 0 | 1 | 2 | 3 |
0 | 1 | 1 | ||
1 | 1 | 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创建的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!