之前在(一百二十八)Android P WIFI启动流程梳理 梳理了WiFi的启动流程,其中有个环节是和interface创建相关的,扒一下具体流程。
主要看下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描述的很精炼
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 down
return null;
}
if (!validateInterfaceCache(chipInfos)) {
Log.e(TAG, "createIface: local cache is invalid!");
stopWifi(); // major error: shutting down
return null;
}
IWifiIface iface = createIfaceIfPossible(chipInfos, ifaceType, lowPriority,
destroyedListener, handler);
if (iface != null) { // means that some configuration has changed
if (!dispatchAvailableForRequestListeners()) {
return null; // catastrophic failure - shut down
}
}
return iface;
}
}
/**
* 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> chipIdsResp = new Mutable<>();
// get all chip IDs
mWifi.getChipIds((WifiStatus status, ArrayList 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 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> availableModesResp = new Mutable<>();
chipResp.value.getAvailableModes(
(WifiStatus status, ArrayList 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> ifaceNamesResp = new Mutable<>();
MutableInt ifaceIndex = new MutableInt(0);
chipResp.value.getStaIfaceNames(
(WifiStatus status, ArrayList 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 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 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 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 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 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 availableCombinations;
};
MutableBoolean statusOk = new MutableBoolean(false);
Mutable> chipIdsResp = new Mutable<>();
// get all chip IDs
mWifi.getChipIds((WifiStatus status, ArrayList 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 Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
&Wifi::getChipIdsInternal, hidl_status_cb);
}
std::pair> Wifi::getChipIdsInternal() {
std::vector 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
Mutable 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 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> 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;
}
Mutable> availableModesResp = new Mutable<>();
chipResp.value.getAvailableModes(
(WifiStatus status, ArrayList 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 WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::getAvailableModesInternal,
hidl_status_cb);
}
std::pair>
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::ChipIfaceCombinationLimit
chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
const IWifiChip::ChipIfaceCombinationLimit
chip_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::ChipIfaceCombinationLimit
sta_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::ChipIfaceCombinationLimit
ap_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;
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 WifiChip::getMode(getMode_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::getModeInternal, hidl_status_cb);
}
std::pair 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* 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)
Mutable> ifaceNamesResp = new Mutable<>();
MutableInt ifaceIndex = new MutableInt(0);
chipResp.value.getStaIfaceNames(
(WifiStatus status, ArrayList 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 WifiChip::getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::getStaIfaceNamesInternal, hidl_status_cb);
}
std::pair>
WifiChip::getStaIfaceNamesInternal() {
if (sta_ifaces_.empty()) {
return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
}
return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)};
}
std::pair> WifiChip::createStaIfaceInternal() {
if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
std::string ifname = allocateApOrStaIfaceName();
sp 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 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> 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
sp findUsingName(std::vector>& ifaces,
const std::string& name) {
std::vector names;
for (const auto& iface : ifaces) {
if (name == iface->getName()) {
return iface;
}
}
return nullptr;
}
用刚才的获取到的接口名称来获取对应的iface
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
synchronized (mLock) {
IfaceCreationData bestIfaceCreationProposal = null;
for (WifiChipInfo chipInfo: chipInfos) {
//暂时只有一个芯片信息
for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) {
//对应于
支持的模式有讲的清楚,先区分是否支持DualInterface
1)若支持
i 支持ap,则模式单一,组合有2种,为sta+p2p 或者sta+ap,标记为kV2ChipModeId
ii 不支持ap,则模式单一,组合有1种,为sta + p2p,标记为kV2ChipModeId
2)若不支持
i 支持ap,则模式有sta+p2p 或者ap,标记为kV1ApChipModeId
ii 不支持ap,则模式单一,为sta+p2p,标记为kV1StaChipModeId
for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode
.availableCombinations) {
对应不同的模式有不同的combinations
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;
}
}
}
}
}
/**
* 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 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 = 1
for (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=2
struct ChipIfaceCombination {
vec 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用二维数组表示了下。待续。。。
/**
* 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 interface
if (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 go
IfaceCreationData ifaceCreationData = new IfaceCreationData();
ifaceCreationData.chipInfo = chipInfo;
ifaceCreationData.chipModeId = chipMode.id;
return ifaceCreationData;
}
// possibly supported
List 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 well
if (type == ifaceType) {
tooManyInterfaces += 1;
}
if (tooManyInterfaces > 0) { // may need to delete some
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,
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 interfaces
interfacesToBeRemovedFirst = 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 interfaces
int numAvailableLowPriorityInterfaces = 0;
for (InterfaceCacheEntry entry : mInterfaceInfoCache.values()) {
if (entry.type == existingIfaceType && entry.isLowPriority) {
numAvailableLowPriorityInterfaces++;
}
}
if (numAvailableLowPriorityInterfaces >= numNecessaryInterfaces) {
return true;
}
// rule 1
if (existingIfaceType == requestedIfaceType) {
return false;
}
// rule 2
if (currentIfaces[requestedIfaceType].length != 0) {
return false;
}
// rule 3
if (currentIfaces[existingIfaceType].length > 1) {
return true;
}
// rule 6
if (requestedIfaceType == IfaceType.NAN) {
return false;
}
// rule 5
if (requestedIfaceType == IfaceType.P2P) {
return existingIfaceType == IfaceType.NAN;
}
// rule 4, the requestIfaceType is either AP or STA
return true;
}
/**
* 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 null
if (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 change
int 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 coin
if (VDBG) Log.d(TAG, "proposals identical - flip a coin");
return false;
}
比较待选选项,移除较少的接口的方案优先。
/**
* 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 modes
if (isModeConfigNeeded) {
// remove all interfaces pre mode-change
// TODO: is this necessary? note that even if we don't want to explicitly
// remove the interfaces we do need to call the onDeleted callbacks - which
// this does
for (WifiIfaceInfo[] ifaceInfos: ifaceCreationData.chipInfo.ifaces) {
for (WifiIfaceInfo ifaceInfo: ifaceInfos) {
removeIfaceInternal(ifaceInfo.iface); // ignore return value
}
}
WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip(
ifaceCreationData.chipModeId);
if (status.code != WifiStatusCode.SUCCESS) {
Log.e(TAG, "executeChipReconfiguration: configureChip error: "
+ statusString(status));
return null;
}
} else {
// remove all interfaces on the delete list
for (WifiIfaceInfo ifaceInfo: ifaceCreationData.interfacesToBeRemovedFirst) {
removeIfaceInternal(ifaceInfo.iface); // ignore return value
}
}
// create new interface
Mutable statusResp = new Mutable<>();
Mutable ifaceResp = new Mutable<>();
switch (ifaceType) {
case IfaceType.STA:
ifaceCreationData.chipInfo.chip.createStaIface(
(WifiStatus status, IWifiStaIface iface) -> {
statusResp.value = status;
ifaceResp.value = iface;
});
break;
hardware/interfaces/wifi/1.2/default/wifi_chip.cpp
Return 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* 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* 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.
Return WifiChip::createStaIface(createStaIface_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::createStaIfaceInternal, hidl_status_cb);
}
std::pair> WifiChip::createStaIfaceInternal() {
if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
std::string ifname = allocateApOrStaIfaceName();
sp 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,待续
本文主要就根据chip info创建sta iface的流程进行了梳理,说明了一个浅显的道理,上层功能受底层限制或软件受限于硬件。