wifi: Add STA + STA HIDL API's

Add the HIDL API's + shim + VTS tests.

Bug: 170305665
Test: atest VtsHalWifiV1_3TargetTest VtsHalWifiV1_5TargetTest
Change-Id: I26ada11aebfe8082bfda251cf7e6990e0aa08a06
This commit is contained in:
Roshan Pius
2020-11-04 11:44:16 -08:00
parent 1bb5ef0b00
commit e9d1e7d384
20 changed files with 606 additions and 57 deletions

View File

@@ -21,6 +21,7 @@
#include <android/hardware/wifi/1.3/IWifi.h>
#include <android/hardware/wifi/1.3/IWifiStaIface.h>
#include <android/hardware/wifi/1.5/IWifiStaIface.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
@@ -88,7 +89,6 @@ TEST_P(WifiStaIfaceHidlTest, GetLinkLayerStats_1_3) {
// No-op if link layer stats is not supported.
return;
}
// Enable link layer stats collection.
EXPECT_EQ(WifiStatusCode::SUCCESS,
HIDL_INVOKE(wifi_sta_iface_, enableLinkLayerStatsCollection, true)
@@ -96,8 +96,17 @@ TEST_P(WifiStaIfaceHidlTest, GetLinkLayerStats_1_3) {
// Retrieve link layer stats.
const auto& status_and_stats =
HIDL_INVOKE(wifi_sta_iface_, getLinkLayerStats_1_3);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_stats.first.code);
EXPECT_GT(status_and_stats.second.timeStampInMs, 0u);
sp<android::hardware::wifi::V1_5::IWifiStaIface> staIface1_5 =
android::hardware::wifi::V1_5::IWifiStaIface::castFrom(wifi_sta_iface_);
if (staIface1_5.get() == nullptr) {
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_stats.first.code);
EXPECT_GT(status_and_stats.second.timeStampInMs, 0u);
} else {
// not supported on 1.5 HAL.
EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED,
status_and_stats.first.code);
}
// Disable link layer stats collection.
EXPECT_EQ(
WifiStatusCode::SUCCESS,

View File

@@ -9,6 +9,7 @@ hidl_interface {
"IWifiChip.hal",
"IWifiNanIface.hal",
"IWifiNanIfaceEventCallback.hal",
"IWifiStaIface.hal",
],
interfaces: [
"android.hardware.wifi@1.0",

View File

@@ -35,6 +35,53 @@ interface IWifiChip extends @1.4::IWifiChip {
WIGIG = 1 << 14,
};
/**
* When there are 2 or more simultaneous STA connections, this use case hint indicates what
* use-case is being enabled by the framework. This use case hint can be used by the firmware
* to modify various firmware configurations like:
* - Allowed BSSIDs the firmware can choose for the initial connection/roaming attempts.
* - Duty cycle to choose for the 2 STA connections if the radio is in MCC mode.
* - Whether roaming, APF and other offloads needs to be enabled or not.
* Note:
* - This will be invoked before an active wifi connection is established on the second
* interface.
* - This use-case hint is implicitly void when the second STA interface is brought down.
*/
enum MultiStaUseCase : uint8_t {
/**
* Usage:
* - This will be sent down for make before break use-case.
* - Platform is trying to speculatively connect to a second network and evaluate it without
* disrupting the primary connection.
* Requirements for Firmware:
* - Do not reduce the number of tx/rx chains of primary connection.
* - If using MCC, should set the MCC duty cycle of the primary connection to be higher than
* the secondary connection (maybe 70/30 split).
* - Should pick the best BSSID for the secondary STA (disregard the chip mode) independent
* of the primary STA:
* - Dont optimize for DBS vs MCC/SCC
* - Should not impact the primary connections bssid selection:
* - Dont downgrade chains of the existing primary connection.
* - Dont optimize for DBS vs MCC/SCC.
*/
DUAL_STA_TRANSIENT_PREFER_PRIMARY = 0,
/**
* Usage:
* - This will be sent down for any app requested peer to peer connections.
* - In this case, both the connections needs to be allocated equal resources.
* - For the peer to peer use case, BSSID for the secondary connection will be chosen by the
* framework.
*
* Requirements for Firmware:
* - Can choose MCC or DBS mode depending on the MCC efficiency and HW capability.
* - If using MCC, set the MCC duty cycle of the primary connection to be equal to the
* secondary connection.
* - Prefer BSSID candidates which will help provide the best "overall" performance for both
* the connections.
*/
DUAL_STA_NON_TRANSIENT_UNBIASED = 1,
};
/**
* Get the capabilities supported by this chip.
*
@@ -48,4 +95,36 @@ interface IWifiChip extends @1.4::IWifiChip {
*/
getCapabilities_1_5()
generates (WifiStatus status, bitfield<ChipCapabilityMask> capabilities);
/**
* Invoked to indicate that the provided iface is the primary STA iface when there are more
* than 1 STA iface concurrently active.
* Note: If the wifi firmware/chip cannot support multiple instances of any offload
* (like roaming, APF, rssi threshold, etc), the firmware should ensure that these
* offloads are at least enabled for the primary interface. If the new primary interface is
* already connected to a network, the firmware must switch all the offloads on
* this new interface without disconnecting.
*
* @param ifname Name of the STA iface.
* @return status WifiStatus of the operation.
* Possible status codes:
* |WifiStatusCode.SUCCESS|,
* |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
* |WifiStatusCode.ERROR_INVALID_ARGS|
*/
setMultiStaPrimaryConnection(string ifName) generates (WifiStatus status);
/**
* Invoked to indicate the STA + STA use-case that is active.
*
* Refer to documentation of |MultiStaUseCase| for details.
*
* @param useCase Use case that is active.
* @return status WifiStatus of the operation.
* Possible status codes:
* |WifiStatusCode.SUCCESS|,
* |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
* |WifiStatusCode.ERROR_INVALID_ARGS|
*/
setMultiStaUseCase(MultiStaUseCase useCase) generates (WifiStatus status);
};

View File

@@ -92,13 +92,12 @@ interface IWifiNanIface extends @1.4::IWifiNanIface {
* |WifiStatusCode.SUCCESS|,
* |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|
*/
registerEventCallback_1_5(IWifiNanIfaceEventCallback callback)
generates (WifiStatus status);
registerEventCallback_1_5(IWifiNanIfaceEventCallback callback) generates (WifiStatus status);
/**
* Get NAN capabilities. Asynchronous response is with
* |IWifiNanIfaceEventCallback.notifyCapabilitiesResponse|.
*
* Note: supersedes the @1.0::IWifiNanIface.getCapabilitiesRequest() method which is deprecated
* as of HAL version 1.5.
*
@@ -109,5 +108,5 @@ interface IWifiNanIface extends @1.4::IWifiNanIface {
* |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
* |WifiStatusCode.ERROR_UNKNOWN|
*/
getCapabilitiesRequest_1_5(CommandIdShort cmdId) generates (WifiStatus status);
};
getCapabilitiesRequest_1_5(CommandIdShort cmdId) generates (WifiStatus status);
};

View File

@@ -40,5 +40,5 @@ interface IWifiNanIfaceEventCallback extends @1.2::IWifiNanIfaceEventCallback {
* @param capabilities Capability data.
*/
oneway notifyCapabilitiesResponse_1_5(CommandIdShort id, WifiNanStatus status,
NanCapabilities capabilities);
};
NanCapabilities capabilities);
};

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2020 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@1.5;
import @1.0::WifiStatus;
import @1.3::IWifiStaIface;
/**
* Interface used to represent a single STA iface.
*
* IWifiChip.createStaIface() must return a @1.5::IWifiStaIface when supported.
*/
interface IWifiStaIface extends @1.3::IWifiStaIface {
/**
* Retrieve the latest link layer stats.
* Must fail if |StaIfaceCapabilityMask.LINK_LAYER_STATS| is not set or if
* link layer stats collection hasn't been explicitly enabled.
*
* @return status WifiStatus of the operation.
* Possible status codes:
* |WifiStatusCode.SUCCESS|,
* |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
* |WifiStatusCode.ERROR_NOT_SUPPORTED|,
* |WifiStatusCode.ERROR_NOT_STARTED|,
* |WifiStatusCode.ERROR_NOT_AVAILABLE|,
* |WifiStatusCode.ERROR_UNKNOWN|
* @return stats Instance of |LinkLayerStats|.
*/
getLinkLayerStats_1_5() generates (WifiStatus status, StaLinkLayerStats stats);
};

View File

@@ -866,46 +866,48 @@ bool convertLegacyLinkLayerRadioStatsToHidl(
bool convertLegacyLinkLayerStatsToHidl(
const legacy_hal::LinkLayerStats& legacy_stats,
V1_3::StaLinkLayerStats* hidl_stats) {
StaLinkLayerStats* hidl_stats) {
if (!hidl_stats) {
return false;
}
*hidl_stats = {};
// iface legacy_stats conversion.
hidl_stats->iface.beaconRx = legacy_stats.iface.beacon_rx;
hidl_stats->iface.avgRssiMgmt = legacy_stats.iface.rssi_mgmt;
hidl_stats->iface.wmeBePktStats.rxMpdu =
hidl_stats->iface.V1_0.beaconRx = legacy_stats.iface.beacon_rx;
hidl_stats->iface.V1_0.avgRssiMgmt = legacy_stats.iface.rssi_mgmt;
hidl_stats->iface.V1_0.wmeBePktStats.rxMpdu =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu;
hidl_stats->iface.wmeBePktStats.txMpdu =
hidl_stats->iface.V1_0.wmeBePktStats.txMpdu =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu;
hidl_stats->iface.wmeBePktStats.lostMpdu =
hidl_stats->iface.V1_0.wmeBePktStats.lostMpdu =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost;
hidl_stats->iface.wmeBePktStats.retries =
hidl_stats->iface.V1_0.wmeBePktStats.retries =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries;
hidl_stats->iface.wmeBkPktStats.rxMpdu =
hidl_stats->iface.V1_0.wmeBkPktStats.rxMpdu =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu;
hidl_stats->iface.wmeBkPktStats.txMpdu =
hidl_stats->iface.V1_0.wmeBkPktStats.txMpdu =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu;
hidl_stats->iface.wmeBkPktStats.lostMpdu =
hidl_stats->iface.V1_0.wmeBkPktStats.lostMpdu =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost;
hidl_stats->iface.wmeBkPktStats.retries =
hidl_stats->iface.V1_0.wmeBkPktStats.retries =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries;
hidl_stats->iface.wmeViPktStats.rxMpdu =
hidl_stats->iface.V1_0.wmeViPktStats.rxMpdu =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu;
hidl_stats->iface.wmeViPktStats.txMpdu =
hidl_stats->iface.V1_0.wmeViPktStats.txMpdu =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu;
hidl_stats->iface.wmeViPktStats.lostMpdu =
hidl_stats->iface.V1_0.wmeViPktStats.lostMpdu =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost;
hidl_stats->iface.wmeViPktStats.retries =
hidl_stats->iface.V1_0.wmeViPktStats.retries =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries;
hidl_stats->iface.wmeVoPktStats.rxMpdu =
hidl_stats->iface.V1_0.wmeVoPktStats.rxMpdu =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu;
hidl_stats->iface.wmeVoPktStats.txMpdu =
hidl_stats->iface.V1_0.wmeVoPktStats.txMpdu =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu;
hidl_stats->iface.wmeVoPktStats.lostMpdu =
hidl_stats->iface.V1_0.wmeVoPktStats.lostMpdu =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost;
hidl_stats->iface.wmeVoPktStats.retries =
hidl_stats->iface.V1_0.wmeVoPktStats.retries =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
hidl_stats->iface.timeSliceDutyCycleInPercent =
legacy_stats.iface.info.time_slicing_duty_cycle_percent;
// radio legacy_stats conversion.
std::vector<V1_3::StaLinkLayerRadioStats> hidl_radios_stats;
for (const auto& legacy_radio_stats : legacy_stats.radios) {
@@ -2787,6 +2789,17 @@ legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(
}
CHECK(false);
}
legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy(
IWifiChip::MultiStaUseCase use_case) {
switch (use_case) {
case IWifiChip::MultiStaUseCase::DUAL_STA_TRANSIENT_PREFER_PRIMARY:
return legacy_hal::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY;
case IWifiChip::MultiStaUseCase::DUAL_STA_NON_TRANSIENT_UNBIASED:
return legacy_hal::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED;
}
CHECK(false);
}
} // namespace hidl_struct_util
} // namespace implementation
} // namespace V1_5

View File

@@ -69,6 +69,8 @@ bool convertLegacyWifiMacInfosToHidl(
hidl_radio_mode_infos);
legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(
IfaceType hidl_interface_type);
legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy(
IWifiChip::MultiStaUseCase use_case);
// STA iface conversion methods.
bool convertLegacyFeaturesToHidlStaCapabilities(
@@ -96,7 +98,7 @@ bool convertLegacyVectorOfCachedGscanResultsToHidl(
std::vector<StaScanData>* hidl_scan_datas);
bool convertLegacyLinkLayerStatsToHidl(
const legacy_hal::LinkLayerStats& legacy_stats,
V1_3::StaLinkLayerStats* hidl_stats);
StaLinkLayerStats* hidl_stats);
bool convertLegacyRoamingCapabilitiesToHidl(
const legacy_hal::wifi_roaming_capabilities& legacy_caps,
StaRoamingCapabilities* hidl_caps);

View File

@@ -154,6 +154,8 @@ TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) {
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost = rand();
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries = rand();
legacy_stats.iface.info.time_slicing_duty_cycle_percent = rand();
for (auto& radio : legacy_stats.radios) {
radio.stats.on_time = rand();
radio.stats.tx_time = rand();
@@ -182,46 +184,49 @@ TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) {
radio.channel_stats.push_back(channel_stat2);
}
V1_3::StaLinkLayerStats converted{};
V1_5::StaLinkLayerStats converted{};
hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
&converted);
EXPECT_EQ(legacy_stats.iface.beacon_rx, converted.iface.beaconRx);
EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.avgRssiMgmt);
EXPECT_EQ(legacy_stats.iface.beacon_rx, converted.iface.V1_0.beaconRx);
EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.V1_0.avgRssiMgmt);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu,
converted.iface.wmeBePktStats.rxMpdu);
converted.iface.V1_0.wmeBePktStats.rxMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu,
converted.iface.wmeBePktStats.txMpdu);
converted.iface.V1_0.wmeBePktStats.txMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost,
converted.iface.wmeBePktStats.lostMpdu);
converted.iface.V1_0.wmeBePktStats.lostMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries,
converted.iface.wmeBePktStats.retries);
converted.iface.V1_0.wmeBePktStats.retries);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu,
converted.iface.wmeBkPktStats.rxMpdu);
converted.iface.V1_0.wmeBkPktStats.rxMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu,
converted.iface.wmeBkPktStats.txMpdu);
converted.iface.V1_0.wmeBkPktStats.txMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost,
converted.iface.wmeBkPktStats.lostMpdu);
converted.iface.V1_0.wmeBkPktStats.lostMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries,
converted.iface.wmeBkPktStats.retries);
converted.iface.V1_0.wmeBkPktStats.retries);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu,
converted.iface.wmeViPktStats.rxMpdu);
converted.iface.V1_0.wmeViPktStats.rxMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu,
converted.iface.wmeViPktStats.txMpdu);
converted.iface.V1_0.wmeViPktStats.txMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost,
converted.iface.wmeViPktStats.lostMpdu);
converted.iface.V1_0.wmeViPktStats.lostMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries,
converted.iface.wmeViPktStats.retries);
converted.iface.V1_0.wmeViPktStats.retries);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu,
converted.iface.wmeVoPktStats.rxMpdu);
converted.iface.V1_0.wmeVoPktStats.rxMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu,
converted.iface.wmeVoPktStats.txMpdu);
converted.iface.V1_0.wmeVoPktStats.txMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost,
converted.iface.wmeVoPktStats.lostMpdu);
converted.iface.V1_0.wmeVoPktStats.lostMpdu);
EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries,
converted.iface.wmeVoPktStats.retries);
converted.iface.V1_0.wmeVoPktStats.retries);
EXPECT_EQ(legacy_stats.iface.info.time_slicing_duty_cycle_percent,
converted.iface.timeSliceDutyCycleInPercent);
EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size());
for (size_t i = 0; i < legacy_stats.radios.size(); i++) {

View File

@@ -678,6 +678,20 @@ Return<void> WifiChip::registerEventCallback_1_4(
hidl_status_cb, event_callback);
}
Return<void> WifiChip::setMultiStaPrimaryConnection(
const hidl_string& ifname, setMultiStaPrimaryConnection_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::setMultiStaPrimaryConnectionInternal,
hidl_status_cb, ifname);
}
Return<void> WifiChip::setMultiStaUseCase(
MultiStaUseCase use_case, setMultiStaUseCase_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::setMultiStaUseCaseInternal,
hidl_status_cb, use_case);
}
void WifiChip::invalidateAndRemoveAllIfaces() {
invalidateAndClearAll(ap_ifaces_);
invalidateAndClearAll(nan_ifaces_);
@@ -1016,7 +1030,7 @@ WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) {
return createWifiStatus(WifiStatusCode::SUCCESS);
}
std::pair<WifiStatus, sp<V1_3::IWifiStaIface>>
std::pair<WifiStatus, sp<V1_5::IWifiStaIface>>
WifiChip::createStaIfaceInternal() {
if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::STA)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
@@ -1050,7 +1064,7 @@ WifiChip::getStaIfaceNamesInternal() {
return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)};
}
std::pair<WifiStatus, sp<V1_3::IWifiStaIface>> WifiChip::getStaIfaceInternal(
std::pair<WifiStatus, sp<V1_5::IWifiStaIface>> WifiChip::getStaIfaceInternal(
const std::string& ifname) {
const auto iface = findUsingName(sta_ifaces_, ifname);
if (!iface.get()) {
@@ -1295,6 +1309,19 @@ WifiStatus WifiChip::registerEventCallbackInternal_1_4(
return createWifiStatus(WifiStatusCode::SUCCESS);
}
WifiStatus WifiChip::setMultiStaPrimaryConnectionInternal(
const std::string& ifname) {
auto legacy_status =
legacy_hal_.lock()->multiStaSetPrimaryConnection(ifname);
return createWifiStatusFromLegacyError(legacy_status);
}
WifiStatus WifiChip::setMultiStaUseCaseInternal(MultiStaUseCase use_case) {
auto legacy_status = legacy_hal_.lock()->multiStaSetUseCase(
hidl_struct_util::convertHidlMultiStaUseCaseToLegacy(use_case));
return createWifiStatusFromLegacyError(legacy_status);
}
WifiStatus WifiChip::handleChipConfiguration(
/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
ChipModeId mode_id) {

View File

@@ -163,6 +163,12 @@ class WifiChip : public V1_5::IWifiChip {
Return<void> registerEventCallback_1_4(
const sp<V1_4::IWifiChipEventCallback>& event_callback,
registerEventCallback_1_4_cb hidl_status_cb) override;
Return<void> setMultiStaPrimaryConnection(
const hidl_string& ifname,
setMultiStaPrimaryConnection_cb hidl_status_cb) override;
Return<void> setMultiStaUseCase(
MultiStaUseCase use_case,
setMultiStaUseCase_cb hidl_status_cb) override;
private:
void invalidateAndRemoveAllIfaces();
@@ -201,9 +207,9 @@ class WifiChip : public V1_5::IWifiChip {
std::pair<WifiStatus, sp<IWifiP2pIface>> getP2pIfaceInternal(
const std::string& ifname);
WifiStatus removeP2pIfaceInternal(const std::string& ifname);
std::pair<WifiStatus, sp<V1_3::IWifiStaIface>> createStaIfaceInternal();
std::pair<WifiStatus, sp<V1_5::IWifiStaIface>> createStaIfaceInternal();
std::pair<WifiStatus, std::vector<hidl_string>> getStaIfaceNamesInternal();
std::pair<WifiStatus, sp<V1_3::IWifiStaIface>> getStaIfaceInternal(
std::pair<WifiStatus, sp<V1_5::IWifiStaIface>> getStaIfaceInternal(
const std::string& ifname);
WifiStatus removeStaIfaceInternal(const std::string& ifname);
std::pair<WifiStatus, sp<V1_0::IWifiRttController>>
@@ -233,6 +239,8 @@ class WifiChip : public V1_5::IWifiChip {
createRttControllerInternal_1_4(const sp<IWifiIface>& bound_iface);
WifiStatus registerEventCallbackInternal_1_4(
const sp<V1_4::IWifiChipEventCallback>& event_callback);
WifiStatus setMultiStaPrimaryConnectionInternal(const std::string& ifname);
WifiStatus setMultiStaUseCaseInternal(MultiStaUseCase use_case);
WifiStatus handleChipConfiguration(
std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);

View File

@@ -1510,6 +1510,17 @@ wifi_error WifiLegacyHal::getSupportedIfaceName(uint32_t iface_type,
return res;
}
wifi_error WifiLegacyHal::multiStaSetPrimaryConnection(
const std::string& ifname) {
return global_func_table_.wifi_multi_sta_set_primary_connection(
global_handle_, getIfaceHandle(ifname));
}
wifi_error WifiLegacyHal::multiStaSetUseCase(wifi_multi_sta_use_case use_case) {
return global_func_table_.wifi_multi_sta_set_use_case(global_handle_,
use_case);
}
void WifiLegacyHal::invalidate() {
global_handle_ = nullptr;
iface_name_to_handle_.clear();

View File

@@ -382,6 +382,10 @@ class WifiLegacyHal {
virtual wifi_error deleteVirtualInterface(const std::string& ifname);
wifi_error getSupportedIfaceName(uint32_t iface_type, std::string& ifname);
// STA + STA functions
virtual wifi_error multiStaSetPrimaryConnection(const std::string& ifname);
virtual wifi_error multiStaSetUseCase(wifi_multi_sta_use_case use_case);
private:
// Retrieve interface handles for all the available interfaces.
wifi_error retrieveIfaceHandles();

View File

@@ -147,6 +147,8 @@ bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) {
populateStubFor(&hal_fn->wifi_get_supported_iface_name);
populateStubFor(&hal_fn->wifi_early_initialize);
populateStubFor(&hal_fn->wifi_get_chip_feature_set);
populateStubFor(&hal_fn->wifi_multi_sta_set_primary_connection);
populateStubFor(&hal_fn->wifi_multi_sta_set_use_case);
return true;
}

View File

@@ -163,6 +163,13 @@ Return<void> WifiStaIface::getLinkLayerStats_1_3(
hidl_status_cb);
}
Return<void> WifiStaIface::getLinkLayerStats_1_5(
getLinkLayerStats_1_5_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
&WifiStaIface::getLinkLayerStatsInternal_1_5,
hidl_status_cb);
}
Return<void> WifiStaIface::startRssiMonitoring(
uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
startRssiMonitoring_cb hidl_status_cb) {
@@ -470,6 +477,11 @@ WifiStaIface::getLinkLayerStatsInternal() {
std::pair<WifiStatus, V1_3::StaLinkLayerStats>
WifiStaIface::getLinkLayerStatsInternal_1_3() {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
}
std::pair<WifiStatus, V1_5::StaLinkLayerStats>
WifiStaIface::getLinkLayerStatsInternal_1_5() {
legacy_hal::wifi_error legacy_status;
legacy_hal::LinkLayerStats legacy_stats;
std::tie(legacy_status, legacy_stats) =
@@ -477,7 +489,7 @@ WifiStaIface::getLinkLayerStatsInternal_1_3() {
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
return {createWifiStatusFromLegacyError(legacy_status), {}};
}
V1_3::StaLinkLayerStats hidl_stats;
V1_5::StaLinkLayerStats hidl_stats;
if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
&hidl_stats)) {
return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};

View File

@@ -19,7 +19,7 @@
#include <android-base/macros.h>
#include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
#include <android/hardware/wifi/1.3/IWifiStaIface.h>
#include <android/hardware/wifi/1.5/IWifiStaIface.h>
#include "hidl_callback_util.h"
#include "wifi_iface_util.h"
@@ -35,7 +35,7 @@ using namespace android::hardware::wifi::V1_0;
/**
* HIDL interface object used to control a STA Iface instance.
*/
class WifiStaIface : public V1_3::IWifiStaIface {
class WifiStaIface : public V1_5::IWifiStaIface {
public:
WifiStaIface(const std::string& ifname,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
@@ -78,6 +78,8 @@ class WifiStaIface : public V1_3::IWifiStaIface {
getLinkLayerStats_cb hidl_status_cb) override;
Return<void> getLinkLayerStats_1_3(
getLinkLayerStats_1_3_cb hidl_status_cb) override;
Return<void> getLinkLayerStats_1_5(
getLinkLayerStats_1_5_cb hidl_status_cb) override;
Return<void> startRssiMonitoring(
uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
startRssiMonitoring_cb hidl_status_cb) override;
@@ -138,6 +140,8 @@ class WifiStaIface : public V1_3::IWifiStaIface {
std::pair<WifiStatus, V1_0::StaLinkLayerStats> getLinkLayerStatsInternal();
std::pair<WifiStatus, V1_3::StaLinkLayerStats>
getLinkLayerStatsInternal_1_3();
std::pair<WifiStatus, V1_5::StaLinkLayerStats>
getLinkLayerStatsInternal_1_5();
WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi,
int32_t min_rssi);
WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id);

View File

@@ -16,10 +16,14 @@
package android.hardware.wifi@1.5;
import @1.0::StaLinkLayerIfaceStats;
import @1.0::StaLinkLayerIfacePacketStats;
import @1.0::TimeStampInMs;
import @1.0::WifiBand;
import @1.0::NanCipherSuiteType;
import @1.0::NanCapabilities;
import @1.2::NanConfigRequestSupplemental;
import @1.3::StaLinkLayerRadioStats;
/**
* Wifi bands defined in 80211 spec.
@@ -48,6 +52,7 @@ struct NanConfigRequestSupplemental {
* Baseline information as defined in HAL 1.2.
*/
@1.2::NanConfigRequestSupplemental V1_2;
/**
* Controls whether NAN instant communication mode is enabled.
*/
@@ -62,8 +67,43 @@ struct NanCapabilities {
* Baseline information as defined in HAL 1.0.
*/
@1.0::NanCapabilities V1_0;
/**
* Flag to indicate id instant communication mode is supported.
*/
bool instantCommunicationModeSupportFlag;
};
};
/**
* Iface statistics for the current connection.
*/
struct StaLinkLayerIfaceStats {
/**
* Baseline information as defined in HAL 1.0.
*/
@1.0::StaLinkLayerIfaceStats V1_0;
/**
* Duty cycle for the iface.
* if this iface is being served using time slicing on a radio with one or more ifaces
* (i.e MCC), then the duty cycle assigned to this iface in %.
* If not using time slicing (i.e SCC or DBS), set to 100.
*/
uint8_t timeSliceDutyCycleInPercent;
};
/**
* Link layer stats retrieved via |getLinkLayerStats|.
*/
struct StaLinkLayerStats {
StaLinkLayerIfaceStats iface;
vec<StaLinkLayerRadioStats> radios;
/**
* TimeStamp for each stats sample.
* This is the absolute milliseconds from boot when these stats were
* sampled.
*/
TimeStampInMs timeStampInMs;
};

View File

@@ -14,6 +14,29 @@
// limitations under the License.
//
cc_test {
name: "VtsHalWifiV1_5TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"wifi_chip_hidl_test.cpp",
"wifi_sta_iface_hidl_test.cpp",
],
static_libs: [
"VtsHalWifiV1_0TargetTestUtil",
"android.hardware.wifi@1.0",
"android.hardware.wifi@1.1",
"android.hardware.wifi@1.2",
"android.hardware.wifi@1.3",
"android.hardware.wifi@1.4",
"android.hardware.wifi@1.5",
"libwifi-system-iface",
],
test_suites: [
"general-tests",
"vts",
],
}
// These tests are split out so that they can be conditioned on presence of the
// "android.hardware.wifi.aware" feature.
cc_test {

View File

@@ -0,0 +1,149 @@
/*
* Copyright (C) 2020 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.
*/
#include <VtsHalHidlTargetCallbackBase.h>
#include <android-base/logging.h>
#undef NAN // NAN is defined in bionic/libc/include/math.h:38
#include <android/hardware/wifi/1.4/IWifiChipEventCallback.h>
#include <android/hardware/wifi/1.5/IWifi.h>
#include <android/hardware/wifi/1.5/IWifiChip.h>
#include <android/hardware/wifi/1.5/IWifiStaIface.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
#include "wifi_hidl_call_util.h"
#include "wifi_hidl_test_utils.h"
using ::android::sp;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::wifi::V1_0::ChipModeId;
using ::android::hardware::wifi::V1_0::IfaceType;
using ::android::hardware::wifi::V1_0::IWifiIface;
using ::android::hardware::wifi::V1_0::IWifiStaIface;
using ::android::hardware::wifi::V1_0::WifiDebugRingBufferStatus;
using ::android::hardware::wifi::V1_0::WifiStatus;
using ::android::hardware::wifi::V1_0::WifiStatusCode;
using ::android::hardware::wifi::V1_4::IWifiChipEventCallback;
using ::android::hardware::wifi::V1_5::IWifiChip;
/**
* Fixture to use for all Wifi chip HIDL interface tests.
*/
class WifiChipHidlTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
// Make sure to start with a clean state
stopWifi(GetInstanceName());
wifi_chip_ = IWifiChip::castFrom(getWifiChip(GetInstanceName()));
ASSERT_NE(nullptr, wifi_chip_.get());
}
virtual void TearDown() override { stopWifi(GetInstanceName()); }
protected:
// Helper function to configure the Chip in one of the supported modes.
// Most of the non-mode-configuration-related methods require chip
// to be first configured.
ChipModeId configureChipForIfaceType(IfaceType type, bool expectSuccess) {
ChipModeId mode_id;
EXPECT_EQ(expectSuccess,
configureChipToSupportIfaceType(wifi_chip_, type, &mode_id));
return mode_id;
}
WifiStatusCode createStaIface(sp<IWifiStaIface>* sta_iface) {
const auto& status_and_iface = HIDL_INVOKE(wifi_chip_, createStaIface);
*sta_iface = status_and_iface.second;
return status_and_iface.first.code;
}
std::string getIfaceName(const sp<IWifiIface>& iface) {
const auto& status_and_name = HIDL_INVOKE(iface, getName);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_name.first.code);
return status_and_name.second;
}
std::vector<sp<IWifiStaIface>> create2StaIfacesIfPossible() {
configureChipForIfaceType(IfaceType::STA, true);
sp<IWifiStaIface> iface1, iface2;
EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&iface1));
EXPECT_NE(nullptr, iface1.get());
// Try to create 2nd iface
auto status = createStaIface(&iface2);
if (status != WifiStatusCode::SUCCESS) {
return {iface1};
}
EXPECT_NE(nullptr, iface2.get());
return {iface1, iface2};
}
sp<IWifiChip> wifi_chip_;
private:
std::string GetInstanceName() { return GetParam(); }
};
/*
* setMultiStaPrimaryConnection
*
* Only run if device supports 2 STA ifaces.
*/
TEST_P(WifiChipHidlTest, setMultiStaPrimaryConnection) {
auto ifaces = create2StaIfacesIfPossible();
if (ifaces.size() < 2) {
GTEST_SKIP() << "Device does not support more than 1 STA concurrently";
}
const auto& status = HIDL_INVOKE(wifi_chip_, setMultiStaPrimaryConnection,
getIfaceName(ifaces.front()));
if (status.code != WifiStatusCode::SUCCESS) {
EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status.code);
}
}
/*
* setMultiStaUseCase
*
* Only run if device supports 2 STA ifaces.
*/
TEST_P(WifiChipHidlTest, setMultiStaUseCase) {
auto ifaces = create2StaIfacesIfPossible();
if (ifaces.size() < 2) {
GTEST_SKIP() << "Device does not support more than 1 STA concurrently";
}
const auto& status = HIDL_INVOKE(
wifi_chip_, setMultiStaUseCase,
IWifiChip::MultiStaUseCase::DUAL_STA_TRANSIENT_PREFER_PRIMARY);
if (status.code != WifiStatusCode::SUCCESS) {
EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status.code);
}
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, WifiChipHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
::android::hardware::wifi::V1_5::IWifi::descriptor)),
android::hardware::PrintInstanceNameToString);

View File

@@ -0,0 +1,117 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Staache 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.
*/
#include <numeric>
#include <vector>
#include <android-base/logging.h>
#include <android/hardware/wifi/1.5/IWifi.h>
#include <android/hardware/wifi/1.5/IWifiChip.h>
#include <android/hardware/wifi/1.5/IWifiStaIface.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
#include "wifi_hidl_call_util.h"
#include "wifi_hidl_test_utils.h"
using ::android::sp;
using ::android::hardware::hidl_array;
using ::android::hardware::wifi::V1_0::WifiStatus;
using ::android::hardware::wifi::V1_0::WifiStatusCode;
using ::android::hardware::wifi::V1_5::IWifiChip;
using ::android::hardware::wifi::V1_5::IWifiStaIface;
/**
* Fixture to use for all STA Iface HIDL interface tests.
*/
class WifiStaIfaceHidlTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
// Make sure to start with a clean state
stopWifi(GetInstanceName());
wifi_sta_iface_ =
IWifiStaIface::castFrom(getWifiStaIface(GetInstanceName()));
ASSERT_NE(nullptr, wifi_sta_iface_.get());
}
virtual void TearDown() override { stopWifi(GetInstanceName()); }
protected:
bool isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask cap_mask) {
const auto& status_and_caps =
HIDL_INVOKE(wifi_sta_iface_, getCapabilities);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
return (status_and_caps.second & cap_mask) != 0;
}
WifiStatusCode createStaIface(sp<IWifiStaIface>* sta_iface) {
sp<IWifiChip> wifi_chip =
IWifiChip::castFrom(getWifiChip(GetInstanceName()));
EXPECT_NE(nullptr, wifi_chip.get());
const auto& status_and_iface = HIDL_INVOKE(wifi_chip, createStaIface);
*sta_iface = IWifiStaIface::castFrom(status_and_iface.second);
return status_and_iface.first.code;
}
sp<IWifiStaIface> wifi_sta_iface_;
private:
std::string GetInstanceName() { return GetParam(); }
};
/*
* GetLinkLayerStats_1_5
* Ensures that calls to get link layer stats V1_5 will retrieve a non-empty
* StaLinkLayerStats after link layer stats collection is enabled.
*/
TEST_P(WifiStaIfaceHidlTest, GetLinkLayerStats_1_5) {
if (!isCapabilitySupported(
IWifiStaIface::StaIfaceCapabilityMask::LINK_LAYER_STATS)) {
// No-op if link layer stats is not supported.
return;
}
// Enable link layer stats collection.
EXPECT_EQ(WifiStatusCode::SUCCESS,
HIDL_INVOKE(wifi_sta_iface_, enableLinkLayerStatsCollection, true)
.code);
// Retrieve link layer stats.
const auto& status_and_stats =
HIDL_INVOKE(wifi_sta_iface_, getLinkLayerStats_1_5);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_stats.first.code);
EXPECT_GT(status_and_stats.second.timeStampInMs, 0u);
// Try to create 2nd iface. If yes, it should fill in the duty cycle field.
sp<IWifiStaIface> iface;
auto status = createStaIface(&iface);
if (status == WifiStatusCode::SUCCESS) {
EXPECT_GT(status_and_stats.second.iface.timeSliceDutyCycleInPercent,
0u);
}
// Disable link layer stats collection.
EXPECT_EQ(
WifiStatusCode::SUCCESS,
HIDL_INVOKE(wifi_sta_iface_, disableLinkLayerStatsCollection).code);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiStaIfaceHidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, WifiStaIfaceHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
::android::hardware::wifi::V1_5::IWifi::descriptor)),
android::hardware::PrintInstanceNameToString);