mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
wifi: Adds a new vendor HAL API for MLO SAP
1. Creates a new ApIfaceParams for all types of AP iface creation and deprecated the old APIs. 2. Add usesMlo in ApIface to indicate Iface type for MLO SAP. PS: Also rename isMlo to usesMlo in hostapd hal. Bug: 362355566 Test: Build & manuel Change-Id: I2460d1d00e4884c5ae22f829ec69df458a039175
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
|
||||
// two cases:
|
||||
// 1). this is a frozen version file - do not edit this in any case.
|
||||
// 2). this is a 'current' file. If you make a backwards compatible change to
|
||||
// the interface (from the latest frozen version), the build system will
|
||||
// prompt you to update this file with `m <name>-update-api`.
|
||||
//
|
||||
// You must not make a backward incompatible change to any AIDL file built
|
||||
// with the aidl_interface module type with versions property set. The module
|
||||
// type is used to build AIDL files in a way that they can be used across
|
||||
// independently updatable components of the system. If a device is shipped
|
||||
// with such a backward incompatible change, it has a high risk of breaking
|
||||
// later when a module using the interface is updated, e.g., Mainline modules.
|
||||
|
||||
package android.hardware.wifi;
|
||||
@VintfStability
|
||||
parcelable ApIfaceParams {
|
||||
android.hardware.wifi.IfaceConcurrencyType ifaceType;
|
||||
boolean usesMlo;
|
||||
@nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
|
||||
}
|
||||
@@ -40,4 +40,5 @@ interface IWifiApIface {
|
||||
void setCountryCode(in byte[2] code);
|
||||
void resetToFactoryMacAddress();
|
||||
void setMacAddress(in byte[6] mac);
|
||||
boolean usesMlo();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,13 @@ package android.hardware.wifi;
|
||||
@VintfStability
|
||||
interface IWifiChip {
|
||||
void configureChip(in int modeId);
|
||||
/**
|
||||
* @deprecated This method is deprecated from AIDL v3, newer HALs should use createApOrBridgedApIfaceWithParams.
|
||||
*/
|
||||
@PropagateAllowBlocking android.hardware.wifi.IWifiApIface createApIface();
|
||||
/**
|
||||
* @deprecated This method is deprecated from AIDL v3, newer HALs should use createApOrBridgedApIfaceWithParams.
|
||||
*/
|
||||
@PropagateAllowBlocking android.hardware.wifi.IWifiApIface createBridgedApIface();
|
||||
@PropagateAllowBlocking android.hardware.wifi.IWifiNanIface createNanIface();
|
||||
@PropagateAllowBlocking android.hardware.wifi.IWifiP2pIface createP2pIface();
|
||||
@@ -83,8 +89,12 @@ interface IWifiChip {
|
||||
void triggerSubsystemRestart();
|
||||
void enableStaChannelForPeerNetwork(in int channelCategoryEnableFlag);
|
||||
void setMloMode(in android.hardware.wifi.IWifiChip.ChipMloMode mode);
|
||||
/**
|
||||
* @deprecated This method is deprecated from AIDL v3, newer HALs should use createApOrBridgedApIfaceWithParams.
|
||||
*/
|
||||
@PropagateAllowBlocking android.hardware.wifi.IWifiApIface createApOrBridgedApIface(in android.hardware.wifi.IfaceConcurrencyType iface, in android.hardware.wifi.common.OuiKeyedData[] vendorData);
|
||||
void setVoipMode(in android.hardware.wifi.IWifiChip.VoipMode mode);
|
||||
@PropagateAllowBlocking android.hardware.wifi.IWifiApIface createApOrBridgedApIfaceWithParams(in android.hardware.wifi.ApIfaceParams params);
|
||||
const int NO_POWER_CAP_CONSTANT = 0x7FFFFFFF;
|
||||
@Backing(type="int") @VintfStability
|
||||
enum FeatureSetMask {
|
||||
|
||||
40
wifi/aidl/android/hardware/wifi/ApIfaceParams.aidl
Normal file
40
wifi/aidl/android/hardware/wifi/ApIfaceParams.aidl
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.hardware.wifi;
|
||||
|
||||
import android.hardware.wifi.IfaceConcurrencyType;
|
||||
import android.hardware.wifi.common.OuiKeyedData;
|
||||
|
||||
/**
|
||||
* Parameters to use for setting up the access point interfaces.
|
||||
*/
|
||||
@VintfStability
|
||||
parcelable ApIfaceParams {
|
||||
/**
|
||||
* IfaceConcurrencyType to be created. Takes one of
|
||||
* |IfaceConcurrencyType.AP| or |IfaceConcurrencyType.AP_BRIDGED|
|
||||
*/
|
||||
IfaceConcurrencyType ifaceType;
|
||||
/**
|
||||
* Whether the current iface will be operated on Multi-links on the one MLD device (MLO).
|
||||
*/
|
||||
boolean usesMlo;
|
||||
/**
|
||||
* Optional vendor-specific configuration parameters.
|
||||
*/
|
||||
@nullable OuiKeyedData[] vendorData;
|
||||
}
|
||||
@@ -85,4 +85,11 @@ interface IWifiApIface {
|
||||
* |WifiStatusCode.ERROR_UNKNOWN|
|
||||
*/
|
||||
void setMacAddress(in byte[6] mac);
|
||||
|
||||
/**
|
||||
* Check if ApIface is for an AP using Multi-Link Operation
|
||||
*
|
||||
* @return true if it is MLO iface, false otherwise.
|
||||
*/
|
||||
boolean usesMlo();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.hardware.wifi;
|
||||
|
||||
import android.hardware.wifi.AfcChannelAllowance;
|
||||
import android.hardware.wifi.ApIfaceParams;
|
||||
import android.hardware.wifi.IWifiApIface;
|
||||
import android.hardware.wifi.IWifiChipEventCallback;
|
||||
import android.hardware.wifi.IWifiNanIface;
|
||||
@@ -433,6 +434,9 @@ interface IWifiChip {
|
||||
* reached the maximum allowed (specified in |ChipIfaceCombination|) number
|
||||
* of ifaces of the AP type.
|
||||
*
|
||||
* @deprecated This method is deprecated from AIDL v3, newer HALs should use
|
||||
* createApOrBridgedApIfaceWithParams.
|
||||
*
|
||||
* @return AIDL interface object representing the iface if
|
||||
* successful, null otherwise.
|
||||
* @throws ServiceSpecificException with one of the following values:
|
||||
@@ -450,6 +454,9 @@ interface IWifiChip {
|
||||
* reached the maximum allowed (specified in |ChipIfaceCombination|) number
|
||||
* of ifaces of the AP type.
|
||||
*
|
||||
* @deprecated This method is deprecated from AIDL v3, newer HALs should use
|
||||
* createApOrBridgedApIfaceWithParams.
|
||||
*
|
||||
* @return AIDL interface object representing the iface if
|
||||
* successful, null otherwise.
|
||||
* @throws ServiceSpecificException with one of the following values:
|
||||
@@ -1177,6 +1184,9 @@ interface IWifiChip {
|
||||
* reached the maximum allowed (specified in |ChipIfaceCombination|) number
|
||||
* of ifaces of the AP or AP_BRIDGED type.
|
||||
*
|
||||
* @deprecated This method is deprecated from AIDL v3, newer HALs should use
|
||||
* createApOrBridgedApIfaceWithParams.
|
||||
*
|
||||
* @param iface IfaceConcurrencyType to be created. Takes one of
|
||||
|IfaceConcurrencyType.AP| or |IfaceConcurrencyType.AP_BRIDGED|
|
||||
* @param vendorData Vendor-provided configuration data as a list of |OuiKeyedData|.
|
||||
@@ -1210,4 +1220,22 @@ interface IWifiChip {
|
||||
* |WifiStatusCode.ERROR_UNKNOWN|
|
||||
*/
|
||||
void setVoipMode(in VoipMode mode);
|
||||
|
||||
/**
|
||||
* Create an AP or bridged AP iface on the chip based on ApIfaceParamss.
|
||||
*
|
||||
* Depending on the mode the chip is configured in, the interface creation
|
||||
* may fail (code: |WifiStatusCode.ERROR_NOT_AVAILABLE|) if we've already
|
||||
* reached the maximum allowed (specified in |ChipIfaceCombination|) number
|
||||
* of ifaces of the AP type.
|
||||
*
|
||||
* @return AIDL interface object representing the iface if
|
||||
* successful, null otherwise.
|
||||
* @throws ServiceSpecificException with one of the following values:
|
||||
* |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
|
||||
* |WifiStatusCode.ERROR_NOT_SUPPORTED|,
|
||||
* |WifiStatusCode.ERROR_NOT_AVAILABLE|
|
||||
*/
|
||||
@PropagateAllowBlocking
|
||||
IWifiApIface createApOrBridgedApIfaceWithParams(in ApIfaceParams params);
|
||||
}
|
||||
|
||||
@@ -28,10 +28,12 @@ namespace hardware {
|
||||
namespace wifi {
|
||||
using aidl_return_util::validateAndCall;
|
||||
|
||||
WifiApIface::WifiApIface(const std::string& ifname, const std::vector<std::string>& instances,
|
||||
WifiApIface::WifiApIface(const std::string& ifname, const bool usesMlo,
|
||||
const std::vector<std::string>& instances,
|
||||
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
|
||||
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
|
||||
: ifname_(ifname),
|
||||
uses_mlo_(usesMlo),
|
||||
instances_(instances),
|
||||
legacy_hal_(legacy_hal),
|
||||
iface_util_(iface_util),
|
||||
@@ -50,6 +52,10 @@ std::string WifiApIface::getName() {
|
||||
return ifname_;
|
||||
}
|
||||
|
||||
bool WifiApIface::usesMlo() {
|
||||
return uses_mlo_;
|
||||
}
|
||||
|
||||
void WifiApIface::removeInstance(std::string instance) {
|
||||
instances_.erase(std::remove(instances_.begin(), instances_.end(), instance), instances_.end());
|
||||
}
|
||||
@@ -72,7 +78,7 @@ ndk::ScopedAStatus WifiApIface::setMacAddress(const std::array<uint8_t, 6>& in_m
|
||||
ndk::ScopedAStatus WifiApIface::getFactoryMacAddress(std::array<uint8_t, 6>* _aidl_return) {
|
||||
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
||||
&WifiApIface::getFactoryMacAddressInternal, _aidl_return,
|
||||
instances_.size() > 0 ? instances_[0] : ifname_);
|
||||
getOperatingInstanceName());
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus WifiApIface::resetToFactoryMacAddress() {
|
||||
@@ -90,14 +96,14 @@ std::pair<std::string, ndk::ScopedAStatus> WifiApIface::getNameInternal() {
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus WifiApIface::setCountryCodeInternal(const std::array<uint8_t, 2>& code) {
|
||||
legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setCountryCode(
|
||||
instances_.size() > 0 ? instances_[0] : ifname_, code);
|
||||
legacy_hal::wifi_error legacy_status =
|
||||
legacy_hal_.lock()->setCountryCode(getOperatingInstanceName(), code);
|
||||
return createWifiStatusFromLegacyError(legacy_status);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus WifiApIface::setMacAddressInternal(const std::array<uint8_t, 6>& mac) {
|
||||
// Support random MAC up to 2 interfaces
|
||||
if (instances_.size() == 2) {
|
||||
if (instances_.size() == 2 && !uses_mlo_) {
|
||||
int rbyte = 1;
|
||||
for (auto const& intf : instances_) {
|
||||
std::array<uint8_t, 6> rmac = mac;
|
||||
@@ -131,7 +137,7 @@ std::pair<std::array<uint8_t, 6>, ndk::ScopedAStatus> WifiApIface::getFactoryMac
|
||||
|
||||
ndk::ScopedAStatus WifiApIface::resetToFactoryMacAddressInternal() {
|
||||
std::pair<std::array<uint8_t, 6>, ndk::ScopedAStatus> getMacResult;
|
||||
if (instances_.size() == 2) {
|
||||
if (instances_.size() == 2 && !uses_mlo_) {
|
||||
for (auto const& intf : instances_) {
|
||||
getMacResult = getFactoryMacAddressInternal(intf);
|
||||
LOG(DEBUG) << "Reset MAC to factory MAC on " << intf;
|
||||
@@ -166,6 +172,11 @@ std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiApIface::getBridgedI
|
||||
return {instances_, ndk::ScopedAStatus::ok()};
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus WifiApIface::usesMlo(bool* _aidl_return) {
|
||||
*_aidl_return = uses_mlo_;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace wifi
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
@@ -33,13 +33,15 @@ namespace wifi {
|
||||
*/
|
||||
class WifiApIface : public BnWifiApIface {
|
||||
public:
|
||||
WifiApIface(const std::string& ifname, const std::vector<std::string>& instances,
|
||||
WifiApIface(const std::string& ifname, const bool usesMlo,
|
||||
const std::vector<std::string>& instances,
|
||||
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
|
||||
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
|
||||
// Refer to |WifiChip::invalidate()|.
|
||||
void invalidate();
|
||||
bool isValid();
|
||||
std::string getName();
|
||||
bool usesMlo();
|
||||
void removeInstance(std::string instance);
|
||||
|
||||
// AIDL methods exposed.
|
||||
@@ -49,6 +51,7 @@ class WifiApIface : public BnWifiApIface {
|
||||
ndk::ScopedAStatus getFactoryMacAddress(std::array<uint8_t, 6>* _aidl_return) override;
|
||||
ndk::ScopedAStatus resetToFactoryMacAddress() override;
|
||||
ndk::ScopedAStatus getBridgedInstances(std::vector<std::string>* _aidl_return) override;
|
||||
ndk::ScopedAStatus usesMlo(bool* _aidl_return) override;
|
||||
|
||||
private:
|
||||
// Corresponding worker functions for the AIDL methods.
|
||||
@@ -61,11 +64,18 @@ class WifiApIface : public BnWifiApIface {
|
||||
std::pair<std::vector<std::string>, ndk::ScopedAStatus> getBridgedInstancesInternal();
|
||||
|
||||
std::string ifname_;
|
||||
bool uses_mlo_;
|
||||
std::vector<std::string> instances_;
|
||||
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
|
||||
std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
|
||||
bool is_valid_;
|
||||
|
||||
// The mlo is using one interface but owning two link instances.
|
||||
// The operating should be based on interface.
|
||||
inline std::string getOperatingInstanceName() {
|
||||
return (instances_.size() > 0 && !uses_mlo_) ? instances_[0] : ifname_;
|
||||
};
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WifiApIface);
|
||||
};
|
||||
|
||||
|
||||
@@ -369,7 +369,7 @@ ndk::ScopedAStatus WifiChip::createApIface(std::shared_ptr<IWifiApIface>* _aidl_
|
||||
|
||||
ndk::ScopedAStatus WifiChip::createBridgedApIface(std::shared_ptr<IWifiApIface>* _aidl_return) {
|
||||
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
|
||||
&WifiChip::createBridgedApIfaceInternal, _aidl_return);
|
||||
&WifiChip::createBridgedApIfaceInternal, _aidl_return, false);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus WifiChip::createApOrBridgedApIface(
|
||||
@@ -613,6 +613,13 @@ ndk::ScopedAStatus WifiChip::setVoipMode(const VoipMode in_mode) {
|
||||
&WifiChip::setVoipModeInternal, in_mode);
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus WifiChip::createApOrBridgedApIfaceWithParams(
|
||||
const ApIfaceParams& in_params, std::shared_ptr<IWifiApIface>* _aidl_return) {
|
||||
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
|
||||
&WifiChip::createApOrBridgedApIfaceWithParamsInternal, _aidl_return,
|
||||
in_params);
|
||||
}
|
||||
|
||||
void WifiChip::invalidateAndRemoveAllIfaces() {
|
||||
invalidateAndClearBridgedApAll();
|
||||
invalidateAndClearAll(ap_ifaces_);
|
||||
@@ -797,15 +804,15 @@ ndk::ScopedAStatus WifiChip::createVirtualApInterface(const std::string& apVirtI
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<WifiApIface> WifiChip::newWifiApIface(std::string& ifname) {
|
||||
std::shared_ptr<WifiApIface> WifiChip::newWifiApIface(std::string& ifname, bool usesMlo) {
|
||||
std::vector<std::string> ap_instances;
|
||||
for (auto const& it : br_ifaces_ap_instances_) {
|
||||
if (it.first == ifname) {
|
||||
ap_instances = it.second;
|
||||
}
|
||||
}
|
||||
std::shared_ptr<WifiApIface> iface =
|
||||
ndk::SharedRefBase::make<WifiApIface>(ifname, ap_instances, legacy_hal_, iface_util_);
|
||||
std::shared_ptr<WifiApIface> iface = ndk::SharedRefBase::make<WifiApIface>(
|
||||
ifname, usesMlo, ap_instances, legacy_hal_, iface_util_);
|
||||
ap_ifaces_.push_back(iface);
|
||||
for (const auto& callback : event_cb_handler_.getCallbacks()) {
|
||||
if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
|
||||
@@ -826,47 +833,60 @@ std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> WifiChip::createApI
|
||||
if (!status.isOk()) {
|
||||
return {std::shared_ptr<WifiApIface>(), std::move(status)};
|
||||
}
|
||||
std::shared_ptr<WifiApIface> iface = newWifiApIface(ifname);
|
||||
std::shared_ptr<WifiApIface> iface = newWifiApIface(ifname, false);
|
||||
return {iface, ndk::ScopedAStatus::ok()};
|
||||
}
|
||||
|
||||
std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus>
|
||||
WifiChip::createBridgedApIfaceInternal() {
|
||||
std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> WifiChip::createBridgedApIfaceInternal(
|
||||
bool usesMlo) {
|
||||
if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP_BRIDGED)) {
|
||||
return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
|
||||
}
|
||||
std::vector<std::string> ap_instances = allocateBridgedApInstanceNames();
|
||||
std::string br_ifname;
|
||||
std::vector<std::string> ap_instances = allocateBridgedApInstanceNames(usesMlo);
|
||||
if (ap_instances.size() < 2) {
|
||||
LOG(ERROR) << "Fail to allocate two instances";
|
||||
return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
|
||||
}
|
||||
std::string br_ifname = kApBridgeIfacePrefix + ap_instances[0];
|
||||
for (int i = 0; i < 2; i++) {
|
||||
ndk::ScopedAStatus status = createVirtualApInterface(ap_instances[i]);
|
||||
if (!status.isOk()) {
|
||||
if (i != 0) { // The failure happened when creating second virtual
|
||||
// iface.
|
||||
legacy_hal_.lock()->deleteVirtualInterface(
|
||||
ap_instances.front()); // Remove the first virtual iface.
|
||||
if (usesMlo) {
|
||||
// MLO SoftAp is using single interface with two links. So only need to create 1 interface.
|
||||
br_ifname = allocateApIfaceName();
|
||||
} else {
|
||||
br_ifname = kApBridgeIfacePrefix + ap_instances[0];
|
||||
for (int i = 0; i < 2; i++) {
|
||||
ndk::ScopedAStatus status = createVirtualApInterface(ap_instances[i]);
|
||||
if (!status.isOk()) {
|
||||
if (i != 0) { // The failure happened when creating second virtual
|
||||
// iface.
|
||||
legacy_hal_.lock()->deleteVirtualInterface(
|
||||
ap_instances.front()); // Remove the first virtual iface.
|
||||
}
|
||||
return {nullptr, std::move(status)};
|
||||
}
|
||||
return {nullptr, std::move(status)};
|
||||
}
|
||||
}
|
||||
br_ifaces_ap_instances_[br_ifname] = ap_instances;
|
||||
if (!iface_util_->createBridge(br_ifname)) {
|
||||
LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str();
|
||||
deleteApIface(br_ifname);
|
||||
return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
|
||||
}
|
||||
for (auto const& instance : ap_instances) {
|
||||
// Bind ap instance interface to AP bridge
|
||||
if (!iface_util_->addIfaceToBridge(br_ifname, instance)) {
|
||||
LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str();
|
||||
if (usesMlo) {
|
||||
ndk::ScopedAStatus status = createVirtualApInterface(br_ifname);
|
||||
if (!status.isOk()) {
|
||||
return {nullptr, std::move(status)};
|
||||
}
|
||||
} else {
|
||||
if (!iface_util_->createBridge(br_ifname)) {
|
||||
LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str();
|
||||
deleteApIface(br_ifname);
|
||||
return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
|
||||
}
|
||||
for (auto const& instance : ap_instances) {
|
||||
// Bind ap instance interface to AP bridge
|
||||
if (!iface_util_->addIfaceToBridge(br_ifname, instance)) {
|
||||
LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str();
|
||||
deleteApIface(br_ifname);
|
||||
return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
|
||||
}
|
||||
}
|
||||
}
|
||||
std::shared_ptr<WifiApIface> iface = newWifiApIface(br_ifname);
|
||||
std::shared_ptr<WifiApIface> iface = newWifiApIface(br_ifname, usesMlo);
|
||||
return {iface, ndk::ScopedAStatus::ok()};
|
||||
}
|
||||
|
||||
@@ -876,7 +896,18 @@ WifiChip::createApOrBridgedApIfaceInternal(
|
||||
if (ifaceType == IfaceConcurrencyType::AP) {
|
||||
return createApIfaceInternal();
|
||||
} else if (ifaceType == IfaceConcurrencyType::AP_BRIDGED) {
|
||||
return createBridgedApIfaceInternal();
|
||||
return createBridgedApIfaceInternal(false);
|
||||
} else {
|
||||
return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus>
|
||||
WifiChip::createApOrBridgedApIfaceWithParamsInternal(const ApIfaceParams& params) {
|
||||
if (params.ifaceType == IfaceConcurrencyType::AP) {
|
||||
return createApIfaceInternal();
|
||||
} else if (params.ifaceType == IfaceConcurrencyType::AP_BRIDGED) {
|
||||
return createBridgedApIfaceInternal(params.usesMlo);
|
||||
} else {
|
||||
return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
|
||||
}
|
||||
@@ -925,23 +956,28 @@ ndk::ScopedAStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal(
|
||||
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) {
|
||||
std::vector<std::string> ap_instances = it.second;
|
||||
for (auto const& iface : ap_instances) {
|
||||
if (iface == ifInstanceName) {
|
||||
if (!iface_util_->removeIfaceFromBridge(it.first, iface)) {
|
||||
LOG(ERROR) << "Failed to remove interface: " << ifInstanceName << " from "
|
||||
<< ifname;
|
||||
return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
legacy_hal::wifi_error 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);
|
||||
for (auto const& instance : ap_instances) {
|
||||
if (instance == ifInstanceName) {
|
||||
if (iface->usesMlo()) {
|
||||
LOG(INFO) << "Remove Link " << ifInstanceName << " from " << ifname;
|
||||
} else {
|
||||
if (!iface_util_->removeIfaceFromBridge(it.first, instance)) {
|
||||
LOG(ERROR) << "Failed to remove interface: " << ifInstanceName
|
||||
<< " from " << ifname;
|
||||
return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
legacy_hal::wifi_error legacy_status =
|
||||
legacy_hal_.lock()->deleteVirtualInterface(instance);
|
||||
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
|
||||
LOG(ERROR) << "Failed to del interface: " << instance << " "
|
||||
<< legacyErrorToString(legacy_status);
|
||||
return createWifiStatusFromLegacyError(legacy_status);
|
||||
}
|
||||
}
|
||||
ap_instances.erase(
|
||||
std::remove(ap_instances.begin(), ap_instances.end(), ifInstanceName),
|
||||
@@ -1729,7 +1765,7 @@ std::string WifiChip::getFirstActiveWlanIfaceName() {
|
||||
// If the first active wlan iface is bridged iface.
|
||||
// Return first instance name.
|
||||
for (auto const& it : br_ifaces_ap_instances_) {
|
||||
if (it.first == ap_ifaces_[0]->getName()) {
|
||||
if (it.first == ap_ifaces_[0]->getName() && !ap_ifaces_[0]->usesMlo()) {
|
||||
return it.second[0];
|
||||
}
|
||||
}
|
||||
@@ -1782,9 +1818,19 @@ std::string WifiChip::allocateApIfaceName() {
|
||||
return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
|
||||
}
|
||||
|
||||
std::vector<std::string> WifiChip::allocateBridgedApInstanceNames() {
|
||||
// Check if we have a dedicated iface for AP.
|
||||
std::vector<std::string> instances = getPredefinedApIfaceNames(true);
|
||||
std::vector<std::string> WifiChip::allocateBridgedApInstanceNames(bool usesMlo) {
|
||||
std::vector<std::string> instances;
|
||||
if (usesMlo) {
|
||||
// For MLO AP, the instances are MLO links and it will be maintained in hostapd.
|
||||
// The hostapd will use 0 as an initial link id and 1 as the next.
|
||||
// Considering Android didn't support link reconfiguration. Forcing to use 0 & 1
|
||||
// should work.
|
||||
instances.push_back("0");
|
||||
instances.push_back("1");
|
||||
} else {
|
||||
// Check if we have a dedicated iface for AP.
|
||||
instances = getPredefinedApIfaceNames(true);
|
||||
}
|
||||
if (instances.size() == 2) {
|
||||
return instances;
|
||||
} else {
|
||||
@@ -1856,11 +1902,14 @@ std::string WifiChip::getWlanIfaceNameWithType(IfaceType type, unsigned idx) {
|
||||
|
||||
void WifiChip::invalidateAndClearBridgedApAll() {
|
||||
for (auto const& it : br_ifaces_ap_instances_) {
|
||||
for (auto const& iface : it.second) {
|
||||
iface_util_->removeIfaceFromBridge(it.first, iface);
|
||||
legacy_hal_.lock()->deleteVirtualInterface(iface);
|
||||
const auto iface = findUsingName(ap_ifaces_, it.first);
|
||||
if (!iface->usesMlo()) {
|
||||
for (auto const& iface : it.second) {
|
||||
iface_util_->removeIfaceFromBridge(it.first, iface);
|
||||
legacy_hal_.lock()->deleteVirtualInterface(iface);
|
||||
}
|
||||
iface_util_->deleteBridge(it.first);
|
||||
}
|
||||
iface_util_->deleteBridge(it.first);
|
||||
}
|
||||
br_ifaces_ap_instances_.clear();
|
||||
}
|
||||
@@ -1868,16 +1917,19 @@ void WifiChip::invalidateAndClearBridgedApAll() {
|
||||
void WifiChip::deleteApIface(const std::string& if_name) {
|
||||
if (if_name.empty()) return;
|
||||
// delete bridged interfaces if any
|
||||
for (auto const& it : br_ifaces_ap_instances_) {
|
||||
if (it.first == if_name) {
|
||||
for (auto const& iface : it.second) {
|
||||
iface_util_->removeIfaceFromBridge(if_name, iface);
|
||||
legacy_hal_.lock()->deleteVirtualInterface(iface);
|
||||
const auto iface = findUsingName(ap_ifaces_, if_name);
|
||||
if (!iface->usesMlo()) {
|
||||
for (auto const& it : br_ifaces_ap_instances_) {
|
||||
if (it.first == if_name) {
|
||||
for (auto const& instance : it.second) {
|
||||
iface_util_->removeIfaceFromBridge(if_name, instance);
|
||||
legacy_hal_.lock()->deleteVirtualInterface(instance);
|
||||
}
|
||||
iface_util_->deleteBridge(if_name);
|
||||
br_ifaces_ap_instances_.erase(if_name);
|
||||
// ifname is bridged AP, return here.
|
||||
return;
|
||||
}
|
||||
iface_util_->deleteBridge(if_name);
|
||||
br_ifaces_ap_instances_.erase(if_name);
|
||||
// ifname is bridged AP, return here.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -159,6 +159,8 @@ class WifiChip : public BnWifiChip {
|
||||
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
|
||||
ndk::ScopedAStatus setMloMode(const ChipMloMode in_mode) override;
|
||||
ndk::ScopedAStatus setVoipMode(const VoipMode in_mode) override;
|
||||
ndk::ScopedAStatus createApOrBridgedApIfaceWithParams(
|
||||
const ApIfaceParams& in_params, std::shared_ptr<IWifiApIface>* _aidl_return) override;
|
||||
|
||||
private:
|
||||
void invalidateAndRemoveAllIfaces();
|
||||
@@ -178,12 +180,15 @@ class WifiChip : public BnWifiChip {
|
||||
std::pair<IWifiChip::ChipDebugInfo, ndk::ScopedAStatus> requestChipDebugInfoInternal();
|
||||
std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> requestDriverDebugDumpInternal();
|
||||
std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> requestFirmwareDebugDumpInternal();
|
||||
std::shared_ptr<WifiApIface> newWifiApIface(std::string& ifname);
|
||||
std::shared_ptr<WifiApIface> newWifiApIface(std::string& ifname, bool usesMlo);
|
||||
ndk::ScopedAStatus createVirtualApInterface(const std::string& apVirtIf);
|
||||
std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createApIfaceInternal();
|
||||
std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createBridgedApIfaceInternal();
|
||||
std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createBridgedApIfaceInternal(
|
||||
bool usesMlo);
|
||||
std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createApOrBridgedApIfaceInternal(
|
||||
IfaceConcurrencyType ifaceType, const std::vector<common::OuiKeyedData>& vendorData);
|
||||
std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus>
|
||||
createApOrBridgedApIfaceWithParamsInternal(const ApIfaceParams& params);
|
||||
std::pair<std::vector<std::string>, ndk::ScopedAStatus> getApIfaceNamesInternal();
|
||||
std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> getApIfaceInternal(
|
||||
const std::string& ifname);
|
||||
@@ -258,7 +263,7 @@ class WifiChip : public BnWifiChip {
|
||||
std::string getFirstActiveWlanIfaceName();
|
||||
std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx);
|
||||
std::string allocateApIfaceName();
|
||||
std::vector<std::string> allocateBridgedApInstanceNames();
|
||||
std::vector<std::string> allocateBridgedApInstanceNames(bool usesMlo);
|
||||
std::string allocateStaIfaceName();
|
||||
bool writeRingbufferFilesInternal();
|
||||
std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx);
|
||||
|
||||
@@ -39,5 +39,5 @@ parcelable IfaceParams {
|
||||
android.hardware.wifi.hostapd.ChannelParams[] channelParams;
|
||||
@nullable android.hardware.wifi.common.OuiKeyedData[] vendorData;
|
||||
@nullable String[] instanceIdentities;
|
||||
boolean isMlo;
|
||||
boolean usesMlo;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ parcelable IfaceParams {
|
||||
*/
|
||||
@nullable String[] instanceIdentities;
|
||||
/**
|
||||
* Whether the current iface is MLO.
|
||||
* Whether the current iface is using multi-link operation.
|
||||
*/
|
||||
boolean isMlo;
|
||||
boolean usesMlo;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user