Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9dffd373 authored by Les Lee's avatar Les Lee Committed by Android (Google) Code Review
Browse files

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

parents d01f83b6 94d2824a
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -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);
};
+165 −17
Original line number Diff line number Diff line
@@ -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
+14 −1
Original line number Diff line number Diff line
@@ -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);
};