diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal index dcc927900a..7cf81b572a 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 @@ 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); }; diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp index 1c238c8ec0..f5842fe934 100644 --- a/wifi/1.5/default/wifi_chip.cpp +++ b/wifi/1.5/default/wifi_chip.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -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 void invalidateAndClear(std::vector>& ifaces, sp iface) { @@ -434,6 +436,13 @@ Return WifiChip::createApIface(createApIface_cb hidl_status_cb) { &WifiChip::createApIfaceInternal, hidl_status_cb); } +Return WifiChip::createBridgedApIface( + createBridgedApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createBridgedApIfaceInternal, + hidl_status_cb); +} + Return 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 WifiChip::removeApIface(const hidl_string& ifname, ifname); } +Return 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 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 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> 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 WifiChip::newWifiApIface(std::string& ifname) { sp 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> WifiChip::createApIfaceInternal() { } } setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return iface; +} + +std::pair> 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 iface = newWifiApIface(ifname); + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair> +WifiChip::createBridgedApIfaceInternal() { + if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string br_ifname = kApBridgeIfacePrefix + allocateApIfaceName(); + std::vector 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 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> 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 diff --git a/wifi/1.5/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h index 693d480bda..b7a9ac8e2b 100644 --- a/wifi/1.5/default/wifi_chip.h +++ b/wifi/1.5/default/wifi_chip.h @@ -94,11 +94,16 @@ class WifiChip : public V1_5::IWifiChip { Return requestFirmwareDebugDump( requestFirmwareDebugDump_cb hidl_status_cb) override; Return createApIface(createApIface_cb hidl_status_cb) override; + Return createBridgedApIface( + createBridgedApIface_cb hidl_status_cb) override; Return getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override; Return getApIface(const hidl_string& ifname, getApIface_cb hidl_status_cb) override; Return removeApIface(const hidl_string& ifname, removeApIface_cb hidl_status_cb) override; + Return removeIfaceInstanceFromBridgedApIface( + const hidl_string& brIfaceName, const hidl_string& ifaceInstanceName, + removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) override; Return createNanIface(createNanIface_cb hidl_status_cb) override; Return getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override; Return getNanIface(const hidl_string& ifname, @@ -192,11 +197,16 @@ class WifiChip : public V1_5::IWifiChip { requestDriverDebugDumpInternal(); std::pair> requestFirmwareDebugDumpInternal(); + sp newWifiApIface(std::string& ifname); + WifiStatus createVirtualApInterface(const std::string& apVirtIf); std::pair> createApIfaceInternal(); + std::pair> createBridgedApIfaceInternal(); std::pair> getApIfaceNamesInternal(); std::pair> getApIfaceInternal( const std::string& ifname); WifiStatus removeApIfaceInternal(const std::string& ifname); + WifiStatus removeIfaceInstanceFromBridgedApIfaceInternal( + const std::string& brIfaceName, const std::string& ifInstanceName); std::pair> createNanIfaceInternal(); std::pair> getNanIfaceNamesInternal(); std::pair> 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_; @@ -296,7 +309,7 @@ class WifiChip : public V1_5::IWifiChip { event_cb_handler_; const std::function subsystemCallbackHandler_; - + std::map> br_ifaces_ap_instances_; DISALLOW_COPY_AND_ASSIGN(WifiChip); };