Merge "wifi: Add AP bridge operations support (AP+AP Part 2)"

This commit is contained in:
Les Lee 2020-12-01 00:05:16 +00:00 committed by Android (Google) Code Review
commit 9dffd373ea
3 changed files with 219 additions and 18 deletions

View file

@ -17,6 +17,7 @@
package android.hardware.wifi@1.5;
import @1.0::WifiStatus;
import @1.0::IWifiApIface;
import @1.0::IWifiIface;
import @1.3::IWifiChip;
import @1.4::IWifiChip;
@ -127,4 +128,43 @@ interface IWifiChip extends @1.4::IWifiChip {
* |WifiStatusCode.ERROR_INVALID_ARGS|
*/
setMultiStaUseCase(MultiStaUseCase useCase) generates (WifiStatus status);
/**
* Create bridged IWifiApIface.
*
* Depending on the mode the chip is configured in, the interface creation
* may fail (code: |ERROR_NOT_AVAILABLE|) if we've already reached the maximum
* allowed (specified in |ChipIfaceCombination|) number of ifaces of the AP
* type.
*
* @return status WifiStatus of the operation.
* Possible status codes:
* |WifiStatusCode.SUCCESS|,
* |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
* |WifiStatusCode.ERROR_NOT_SUPPORTED|,
* |WifiStatusCode.ERROR_NOT_AVAILABLE|
* @return iface HIDL interface object representing the iface if
* successful, null otherwise.
*/
createBridgedApIface() generates (WifiStatus status, IWifiApIface iface);
/**
* Removes one of the instance on the AP Iface with the provided ifaceName and
* ifaceInstanceName.
*
* Use the API: removeApIface with brIfaceName in the V1_0::WifiChip.hal to remove bridge Iface.
*
* @param brIfaceName Name of the bridged AP iface.
* @param ifaceInstanceName Name of the instance. The empty instance is
* invalid.
* @return status WifiStatus of the operation.
* Possible status codes:
* |WifiStatusCode.SUCCESS|,
* |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
* |WifiStatusCode.ERROR_INVALID_ARGS|,
* |WifiStatusCode.ERROR_NOT_AVAILABLE|
*/
removeIfaceInstanceFromBridgedApIface(string brIfaceName, string ifaceInstanceName)
generates (WifiStatus status);
};

View file

@ -19,6 +19,7 @@
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <cutils/properties.h>
#include <net/if.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
@ -44,6 +45,7 @@ constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
constexpr char kActiveWlanIfaceNameProperty[] = "wifi.active.interface";
constexpr char kNoActiveWlanIfaceNamePropertyValue[] = "";
constexpr unsigned kMaxWlanIfaces = 5;
constexpr char kApBridgeIfacePrefix[] = "ap_br_";
template <typename Iface>
void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
@ -434,6 +436,13 @@ Return<void> WifiChip::createApIface(createApIface_cb hidl_status_cb) {
&WifiChip::createApIfaceInternal, hidl_status_cb);
}
Return<void> WifiChip::createBridgedApIface(
createBridgedApIface_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::createBridgedApIfaceInternal,
hidl_status_cb);
}
Return<void> WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::getApIfaceNamesInternal, hidl_status_cb);
@ -453,6 +462,15 @@ Return<void> WifiChip::removeApIface(const hidl_string& ifname,
ifname);
}
Return<void> WifiChip::removeIfaceInstanceFromBridgedApIface(
const hidl_string& ifname, const hidl_string& ifInstanceName,
removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) {
return validateAndCall(
this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal,
hidl_status_cb, ifname, ifInstanceName);
}
Return<void> WifiChip::createNanIface(createNanIface_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::createNanIfaceInternal, hidl_status_cb);
@ -693,6 +711,7 @@ Return<void> WifiChip::setMultiStaUseCase(
}
void WifiChip::invalidateAndRemoveAllIfaces() {
invalidateAndClearBridgedApAll();
invalidateAndClearAll(ap_ifaces_);
invalidateAndClearAll(nan_ifaces_);
invalidateAndClearAll(p2p_ifaces_);
@ -861,20 +880,20 @@ WifiChip::requestFirmwareDebugDumpInternal() {
return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump};
}
std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
std::string ifname = allocateApIfaceName();
legacy_hal::wifi_error legacy_status =
legacy_hal_.lock()->createVirtualInterface(
ifname,
WifiStatus WifiChip::createVirtualApInterface(const std::string& apVirtIf) {
legacy_hal::wifi_error legacy_status;
legacy_status = legacy_hal_.lock()->createVirtualInterface(
apVirtIf,
hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
LOG(ERROR) << "Failed to add interface: " << ifname << " "
LOG(ERROR) << "Failed to add interface: " << apVirtIf << " "
<< legacyErrorToString(legacy_status);
return {createWifiStatusFromLegacyError(legacy_status), {}};
return createWifiStatusFromLegacyError(legacy_status);
}
return createWifiStatus(WifiStatusCode::SUCCESS);
}
sp<WifiApIface> WifiChip::newWifiApIface(std::string& ifname) {
sp<WifiApIface> iface = new WifiApIface(ifname, legacy_hal_, iface_util_);
ap_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
@ -883,6 +902,60 @@ std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
}
}
setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
return iface;
}
std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
std::string ifname = allocateApIfaceName();
WifiStatus status = createVirtualApInterface(ifname);
if (status.code != WifiStatusCode::SUCCESS) {
return {status, {}};
}
sp<WifiApIface> iface = newWifiApIface(ifname);
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
}
std::pair<WifiStatus, sp<IWifiApIface>>
WifiChip::createBridgedApIfaceInternal() {
if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
std::string br_ifname = kApBridgeIfacePrefix + allocateApIfaceName();
std::vector<std::string> ap_instances;
for (int i = 0; i < 2; i++) {
// TODO: b/173999527, it should use idx from 2 when STA+STA support, but
// need to check vendor support or not.
std::string ifaceInstanceName = allocateApOrStaIfaceName(
IfaceType::AP, isStaApConcurrencyAllowedInCurrentMode() ? 1 : 0);
WifiStatus status = createVirtualApInterface(ifaceInstanceName);
if (status.code != WifiStatusCode::SUCCESS) {
if (ap_instances.size() != 0) {
legacy_hal_.lock()->deleteVirtualInterface(
ap_instances.front());
}
return {status, {}};
}
ap_instances.push_back(ifaceInstanceName);
}
br_ifaces_ap_instances_[br_ifname] = ap_instances;
if (!iface_util_.lock()->createBridge(br_ifname)) {
LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str();
invalidateAndClearBridgedAp(br_ifname);
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
for (auto const& instance : ap_instances) {
// Bind ap instance interface to AP bridge
if (!iface_util_.lock()->addIfaceToBridge(br_ifname, instance)) {
LOG(ERROR) << "Failed add if to Bridge - if_name="
<< instance.c_str();
invalidateAndClearBridgedAp(br_ifname);
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
}
sp<WifiApIface> iface = newWifiApIface(br_ifname);
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
}
@ -913,12 +986,8 @@ WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
// nan/rtt objects over AP iface. But, there is no harm to do it
// here and not make that assumption all over the place.
invalidateAndRemoveDependencies(ifname);
legacy_hal::wifi_error legacy_status =
legacy_hal_.lock()->deleteVirtualInterface(ifname);
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
LOG(ERROR) << "Failed to remove interface: " << ifname << " "
<< legacyErrorToString(legacy_status);
}
// Clear the bridge interface and the iface instance.
invalidateAndClearBridgedAp(ifname);
invalidateAndClear(ap_ifaces_, iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
@ -929,6 +998,42 @@ WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
return createWifiStatus(WifiStatusCode::SUCCESS);
}
WifiStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal(
const std::string& ifname, const std::string& ifInstanceName) {
legacy_hal::wifi_error legacy_status;
const auto iface = findUsingName(ap_ifaces_, ifname);
if (!iface.get() || !ifInstanceName.empty()) {
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
}
// Requires to remove one of the instance in bridge mode
for (auto const& it : br_ifaces_ap_instances_) {
if (it.first == ifname) {
for (auto const& iface : it.second) {
if (iface == ifInstanceName) {
if (!iface_util_.lock()->removeIfaceFromBridge(it.first,
iface)) {
LOG(ERROR) << "Failed to remove interface: " << iface
<< " from " << ifname << ", error: "
<< legacyErrorToString(legacy_status);
return createWifiStatus(
WifiStatusCode::ERROR_NOT_AVAILABLE);
}
legacy_status =
legacy_hal_.lock()->deleteVirtualInterface(iface);
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
LOG(ERROR) << "Failed to del interface: " << iface
<< " " << legacyErrorToString(legacy_status);
return createWifiStatusFromLegacyError(legacy_status);
}
}
}
break;
}
}
br_ifaces_ap_instances_.erase(ifInstanceName);
return createWifiStatus(WifiStatusCode::SUCCESS);
}
std::pair<WifiStatus, sp<V1_4::IWifiNanIface>>
WifiChip::createNanIfaceInternal() {
if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::NAN)) {
@ -1653,6 +1758,7 @@ std::string WifiChip::allocateApOrStaIfaceName(IfaceType type,
uint32_t start_idx) {
for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) {
const auto ifname = getWlanIfaceNameWithType(type, idx);
if (findUsingNameFromBridgedApInstances(ifname)) continue;
if (findUsingName(ap_ifaces_, ifname)) continue;
if (findUsingName(sta_ifaces_, ifname)) continue;
return ifname;
@ -1727,6 +1833,48 @@ std::string WifiChip::getWlanIfaceNameWithType(IfaceType type, unsigned idx) {
return getWlanIfaceName(idx);
}
void WifiChip::invalidateAndClearBridgedApAll() {
for (auto const& it : br_ifaces_ap_instances_) {
for (auto const& iface : it.second) {
iface_util_.lock()->removeIfaceFromBridge(it.first, iface);
legacy_hal_.lock()->deleteVirtualInterface(iface);
}
iface_util_.lock()->deleteBridge(it.first);
}
br_ifaces_ap_instances_.clear();
}
void WifiChip::invalidateAndClearBridgedAp(const std::string& br_name) {
if (br_name.empty()) return;
// delete managed interfaces
for (auto const& it : br_ifaces_ap_instances_) {
if (it.first == br_name) {
for (auto const& iface : it.second) {
iface_util_.lock()->removeIfaceFromBridge(br_name, iface);
legacy_hal_.lock()->deleteVirtualInterface(iface);
}
iface_util_.lock()->deleteBridge(br_name);
br_ifaces_ap_instances_.erase(br_name);
break;
}
}
return;
}
bool WifiChip::findUsingNameFromBridgedApInstances(const std::string& name) {
for (auto const& it : br_ifaces_ap_instances_) {
if (it.first == name) {
return true;
}
for (auto const& iface : it.second) {
if (iface == name) {
return true;
}
}
}
return false;
}
} // namespace implementation
} // namespace V1_5
} // namespace wifi

View file

@ -94,11 +94,16 @@ class WifiChip : public V1_5::IWifiChip {
Return<void> requestFirmwareDebugDump(
requestFirmwareDebugDump_cb hidl_status_cb) override;
Return<void> createApIface(createApIface_cb hidl_status_cb) override;
Return<void> createBridgedApIface(
createBridgedApIface_cb hidl_status_cb) override;
Return<void> getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override;
Return<void> getApIface(const hidl_string& ifname,
getApIface_cb hidl_status_cb) override;
Return<void> removeApIface(const hidl_string& ifname,
removeApIface_cb hidl_status_cb) override;
Return<void> removeIfaceInstanceFromBridgedApIface(
const hidl_string& brIfaceName, const hidl_string& ifaceInstanceName,
removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) override;
Return<void> createNanIface(createNanIface_cb hidl_status_cb) override;
Return<void> getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override;
Return<void> getNanIface(const hidl_string& ifname,
@ -192,11 +197,16 @@ class WifiChip : public V1_5::IWifiChip {
requestDriverDebugDumpInternal();
std::pair<WifiStatus, std::vector<uint8_t>>
requestFirmwareDebugDumpInternal();
sp<WifiApIface> newWifiApIface(std::string& ifname);
WifiStatus createVirtualApInterface(const std::string& apVirtIf);
std::pair<WifiStatus, sp<IWifiApIface>> createApIfaceInternal();
std::pair<WifiStatus, sp<IWifiApIface>> createBridgedApIfaceInternal();
std::pair<WifiStatus, std::vector<hidl_string>> getApIfaceNamesInternal();
std::pair<WifiStatus, sp<IWifiApIface>> getApIfaceInternal(
const std::string& ifname);
WifiStatus removeApIfaceInternal(const std::string& ifname);
WifiStatus removeIfaceInstanceFromBridgedApIfaceInternal(
const std::string& brIfaceName, const std::string& ifInstanceName);
std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> createNanIfaceInternal();
std::pair<WifiStatus, std::vector<hidl_string>> getNanIfaceNamesInternal();
std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> getNanIfaceInternal(
@ -272,6 +282,9 @@ class WifiChip : public V1_5::IWifiChip {
std::string allocateStaIfaceName();
bool writeRingbufferFilesInternal();
std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx);
void invalidateAndClearBridgedApAll();
void invalidateAndClearBridgedAp(const std::string& br_name);
bool findUsingNameFromBridgedApInstances(const std::string& name);
ChipId chip_id_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
@ -296,7 +309,7 @@ class WifiChip : public V1_5::IWifiChip {
event_cb_handler_;
const std::function<void(const std::string&)> subsystemCallbackHandler_;
std::map<std::string, std::vector<std::string>> br_ifaces_ap_instances_;
DISALLOW_COPY_AND_ASSIGN(WifiChip);
};