wifi: Add AP bridge operations support (AP+AP Part 2)
The bridge interface name will take "ap_br_" + ap interface name.
ex: The ap interface name is "wlan1".
The bridge interface name will be "ap_br_wlan1"
When OEM customize the ap interface name via property
"ro.vendor.wifi.sap.interface".
It will only apply on single AP mode.
i.e.
"ro.vendor.wifi.sap.interface" = "sap0"
Single AP mode: ap interface name = "sap0"
Dual AP mode:
bridge interface name = "ap_br_sap0"
first ap instance name: get from "getSupportedIfaceName" + idx
ex: sap0
second ap instance name: get from "getSupportedIfaceName" + idx + 1
ex: sap1
PS: The VtsHalWifiApV1_5TargetTest will be added in another CL which
will update another SAP related HAL:IWifiApIface.hal.
AP+AP Part 2 includes:
1. Support bridge in libwifi_system_iface
2. WifiHal API
a. createBridgedApIface (Support create bridge mode AP)
b. removeIfaceInstanceFromBridgedApIface (Support remove one of the instance in bridge)
3. Framework:
Create bridge AP when multi-bands configured.
Bug: 162686273
Test: Manual Test (SAP enable normally)
Test: atest -c VtsHalWifiApV1_0TargetTest
Test: atest -c VtsHalWifiApV1_4TargetTest
Change-Id: I8be510778e9772bcf1539e4915384949cbe13127
diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal
index dcc9279..7cf81b5 100644
--- a/wifi/1.5/IWifiChip.hal
+++ b/wifi/1.5/IWifiChip.hal
@@ -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 @@
* |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);
};
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 1c238c8..f5842fe 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -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 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 @@
&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 @@
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 @@
}
void WifiChip::invalidateAndRemoveAllIfaces() {
+ invalidateAndClearBridgedApAll();
invalidateAndClearAll(ap_ifaces_);
invalidateAndClearAll(nan_ifaces_);
invalidateAndClearAll(p2p_ifaces_);
@@ -861,20 +880,20 @@
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,
- hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
+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 @@
}
}
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 @@
// 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 @@
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 @@
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 @@
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
diff --git a/wifi/1.5/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h
index 693d480..b7a9ac8 100644
--- a/wifi/1.5/default/wifi_chip.h
+++ b/wifi/1.5/default/wifi_chip.h
@@ -94,11 +94,16 @@
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 @@
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 @@
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 @@
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);
};