diff --git a/wifi/hostapd/1.3/vts/OWNERS b/wifi/hostapd/1.3/vts/OWNERS new file mode 100644 index 0000000000..8bfb14882c --- /dev/null +++ b/wifi/hostapd/1.3/vts/OWNERS @@ -0,0 +1,2 @@ +rpius@google.com +etancohen@google.com diff --git a/wifi/hostapd/1.3/vts/functional/Android.bp b/wifi/hostapd/1.3/vts/functional/Android.bp new file mode 100644 index 0000000000..07cebb018a --- /dev/null +++ b/wifi/hostapd/1.3/vts/functional/Android.bp @@ -0,0 +1,39 @@ +// +// 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. +// + +cc_test { + name: "VtsHalWifiHostapdV1_3TargetTest", + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "hostapd_hidl_test.cpp", + ], + static_libs: [ + "VtsHalWifiV1_0TargetTestUtil", + "VtsHalWifiHostapdV1_0TargetTestUtil", + "android.hardware.wifi.hostapd@1.0", + "android.hardware.wifi.hostapd@1.1", + "android.hardware.wifi.hostapd@1.2", + "android.hardware.wifi.hostapd@1.3", + "android.hardware.wifi@1.0", + "libgmock", + "libwifi-system", + "libwifi-system-iface", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp new file mode 100644 index 0000000000..d6c750f6c7 --- /dev/null +++ b/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp @@ -0,0 +1,433 @@ +/* + * 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 + +#include +#include + +#include +#include +#include + +#include +#include + +#include "hostapd_hidl_call_util.h" +#include "hostapd_hidl_test_utils.h" + +using ::android::sp; +using ::android::hardware::hidl_string; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::wifi::hostapd::V1_2::DebugLevel; +using ::android::hardware::wifi::hostapd::V1_2::HostapdStatusCode; +using ::android::hardware::wifi::hostapd::V1_2::Ieee80211ReasonCode; +using ::android::hardware::wifi::hostapd::V1_3::IHostapd; +using ::android::hardware::wifi::V1_0::IWifi; + +namespace { +constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1', + '2', '3', '4', '5'}; +constexpr char kNwPassphrase[] = "test12345"; +constexpr char kInvalidMaxPskNwPassphrase[] = + "0123456789012345678901234567890123456789012345678901234567890123456789"; +constexpr char kInvalidMinPskNwPassphrase[] = "test"; +constexpr int kIfaceChannel = 6; +constexpr int kIfaceInvalidChannel = 567; +constexpr uint8_t kTestZeroMacAddr[] = {[0 ... 5] = 0x0}; +constexpr Ieee80211ReasonCode kTestDisconnectReasonCode = + Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED; +} // namespace + +class HostapdHidlTest + : public ::testing::TestWithParam> { + public: + virtual void SetUp() override { + wifi_instance_name_ = std::get<0>(GetParam()); + hostapd_instance_name_ = std::get<1>(GetParam()); + stopSupplicantIfNeeded(wifi_instance_name_); + startHostapdAndWaitForHidlService(wifi_instance_name_, + hostapd_instance_name_); + hostapd_ = IHostapd::getService(hostapd_instance_name_); + ASSERT_NE(hostapd_.get(), nullptr); + HIDL_INVOKE(hostapd_, setDebugParams, DebugLevel::EXCESSIVE); + isAcsSupport_ = testing::checkSubstringInCommandOutput( + "/system/bin/cmd wifi get-softap-supported-features", + "wifi_softap_acs_supported"); + isWpa3SaeSupport_ = testing::checkSubstringInCommandOutput( + "/system/bin/cmd wifi get-softap-supported-features", + "wifi_softap_wpa3_sae_supported"); + } + + virtual void TearDown() override { + HIDL_INVOKE_VOID_WITHOUT_ARGUMENTS(hostapd_, terminate); + stopHostapd(wifi_instance_name_); + } + + protected: + bool isWpa3SaeSupport_ = false; + bool isAcsSupport_ = false; + std::string getPrimaryWlanIfaceName() { + std::array buffer; + auto res = property_get("ro.vendor.wifi.sap.interface", buffer.data(), + nullptr); + if (res > 0) return buffer.data(); + property_get("wifi.interface", buffer.data(), "wlan0"); + return buffer.data(); + } + + IHostapd::IfaceParams getIfaceParamsWithoutAcs() { + ::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams + iface_params; + ::android::hardware::wifi::hostapd::V1_1::IHostapd::IfaceParams + iface_params_1_1; + IHostapd::IfaceParams iface_params_1_2; + + iface_params.ifaceName = getPrimaryWlanIfaceName(); + iface_params.hwModeParams.enable80211N = true; + iface_params.hwModeParams.enable80211AC = false; + iface_params.channelParams.enableAcs = false; + iface_params.channelParams.acsShouldExcludeDfs = false; + iface_params.channelParams.channel = kIfaceChannel; + iface_params_1_1.V1_0 = iface_params; + iface_params_1_2.V1_1 = iface_params_1_1; + // Newly added attributes in V1_2 + iface_params_1_2.hwModeParams.enable80211AX = false; + iface_params_1_2.hwModeParams.enable6GhzBand = false; + iface_params_1_2.channelParams.bandMask = 0; + iface_params_1_2.channelParams.bandMask |= + IHostapd::BandMask::BAND_2_GHZ; + return iface_params_1_2; + } + + IHostapd::IfaceParams getIfaceParamsWithAcs() { + // First get the settings for WithoutAcs and then make changes + IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithoutAcs(); + iface_params_1_2.V1_1.V1_0.channelParams.enableAcs = true; + iface_params_1_2.V1_1.V1_0.channelParams.acsShouldExcludeDfs = true; + iface_params_1_2.V1_1.V1_0.channelParams.channel = 0; + iface_params_1_2.channelParams.bandMask |= + IHostapd::BandMask::BAND_5_GHZ; + + return iface_params_1_2; + } + + IHostapd::IfaceParams getIfaceParamsWithAcsAndFreqRange() { + IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithAcs(); + ::android::hardware::wifi::hostapd::V1_2::IHostapd::AcsFrequencyRange + acsFrequencyRange; + acsFrequencyRange.start = 2412; + acsFrequencyRange.end = 2462; + std::vector<::android::hardware::wifi::hostapd::V1_2::IHostapd:: + AcsFrequencyRange> + vec_acsFrequencyRange; + vec_acsFrequencyRange.push_back(acsFrequencyRange); + iface_params_1_2.channelParams.acsChannelFreqRangesMhz = + vec_acsFrequencyRange; + return iface_params_1_2; + } + + IHostapd::IfaceParams getIfaceParamsWithAcsAndInvalidFreqRange() { + IHostapd::IfaceParams iface_params_1_2 = + getIfaceParamsWithAcsAndFreqRange(); + iface_params_1_2.channelParams.acsChannelFreqRangesMhz[0].start = 222; + iface_params_1_2.channelParams.acsChannelFreqRangesMhz[0].end = 999; + return iface_params_1_2; + } + + IHostapd::NetworkParams getOpenNwParams() { + IHostapd::NetworkParams nw_params_1_3; + ::android::hardware::wifi::hostapd::V1_2::IHostapd::NetworkParams + nw_params_1_2; + ::android::hardware::wifi::hostapd::V1_0::IHostapd::NetworkParams + nw_params_1_0; + nw_params_1_0.ssid = + std::vector(kNwSsid, kNwSsid + sizeof(kNwSsid)); + nw_params_1_0.isHidden = false; + nw_params_1_2.V1_0 = nw_params_1_0; + nw_params_1_2.encryptionType = IHostapd::EncryptionType::NONE; + nw_params_1_3.V1_2 = nw_params_1_2; + nw_params_1_3.isMetered = true; + return nw_params_1_3; + } + + IHostapd::NetworkParams getPskNwParamsWithNonMetered() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA2; + nw_params_1_3.V1_2.passphrase = kNwPassphrase; + nw_params_1_3.isMetered = false; + return nw_params_1_3; + } + + IHostapd::NetworkParams getPskNwParams() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA2; + nw_params_1_3.V1_2.passphrase = kNwPassphrase; + return nw_params_1_3; + } + + IHostapd::NetworkParams getInvalidPskNwParams() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA2; + nw_params_1_3.V1_2.passphrase = kInvalidMaxPskNwPassphrase; + + return nw_params_1_3; + } + + IHostapd::NetworkParams getSaeTransitionNwParams() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = + IHostapd::EncryptionType::WPA3_SAE_TRANSITION; + nw_params_1_3.V1_2.passphrase = kNwPassphrase; + return nw_params_1_3; + } + + IHostapd::NetworkParams getInvalidSaeTransitionNwParams() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA2; + nw_params_1_3.V1_2.passphrase = kInvalidMinPskNwPassphrase; + return nw_params_1_3; + } + + IHostapd::NetworkParams getSaeNwParams() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA3_SAE; + nw_params_1_3.V1_2.passphrase = kNwPassphrase; + return nw_params_1_3; + } + + IHostapd::NetworkParams getInvalidSaeNwParams() { + IHostapd::NetworkParams nw_params_1_3 = getOpenNwParams(); + nw_params_1_3.V1_2.encryptionType = IHostapd::EncryptionType::WPA3_SAE; + nw_params_1_3.V1_2.passphrase = ""; + return nw_params_1_3; + } + + IHostapd::IfaceParams getIfaceParamsWithInvalidChannel() { + IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithoutAcs(); + iface_params_1_2.V1_1.V1_0.channelParams.channel = kIfaceInvalidChannel; + return iface_params_1_2; + } + + // IHostapd object used for all tests in this fixture. + sp hostapd_; + std::string wifi_instance_name_; + std::string hostapd_instance_name_; +}; + +/** + * Adds an access point with PSK network config & ACS enabled. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddPskAccessPointWithAcs) { + if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with PSK network config, ACS enabled & frequency Range. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndFreqRange) { + if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithAcsAndFreqRange(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid channel range. + * Access point creation should fail. + */ +TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidFreqRange) { + if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithAcsAndInvalidFreqRange(), + getPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with Open network config & ACS enabled. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddOpenAccessPointWithAcs) { + if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithAcs(), getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with PSK network config & ACS disabled. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with PSK network config, ACS disabled & Non metered. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcsAndNonMetered) { + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(), + getPskNwParamsWithNonMetered()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with Open network config & ACS disabled. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddOpenAccessPointWithoutAcs) { + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(), getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with SAE Transition network config & ACS disabled. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddSaeTransitionAccessPointWithoutAcs) { + if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support"; + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(), + getSaeTransitionNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with SAE network config & ACS disabled. + * Access point creation should pass. + */ +TEST_P(HostapdHidlTest, AddSAEAccessPointWithoutAcs) { + if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support"; + auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(), getSaeNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds & then removes an access point with PSK network config & ACS enabled. + * Access point creation & removal should pass. + */ +TEST_P(HostapdHidlTest, RemoveAccessPointWithAcs) { + if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support"; + auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code); + auto status = + HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName()); + EXPECT_EQ( + android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS, + status.code); +} + +/** + * Adds & then removes an access point with PSK network config & ACS disabled. + * Access point creation & removal should pass. + */ +TEST_P(HostapdHidlTest, RemoveAccessPointWithoutAcs) { + auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithoutAcs(), getPskNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code); + auto status = + HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName()); + EXPECT_EQ( + android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS, + status.code); +} + +/** + * Adds an access point with invalid channel. + * Access point creation should fail. + */ +TEST_P(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) { + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, + getIfaceParamsWithInvalidChannel(), getPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid PSK network config. + * Access point creation should fail. + */ +TEST_P(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) { + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(), + getInvalidPskNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid SAE transition network config. + * Access point creation should fail. + */ +TEST_P(HostapdHidlTest, AddInvalidSaeTransitionAccessPointWithoutAcs) { + if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support"; + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(), + getInvalidSaeTransitionNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * Adds an access point with invalid SAE network config. + * Access point creation should fail. + */ +TEST_P(HostapdHidlTest, AddInvalidSaeAccessPointWithoutAcs) { + if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support"; + auto status = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(), + getInvalidSaeNwParams()); + EXPECT_NE(HostapdStatusCode::SUCCESS, status.code); +} + +/** + * forceClientDisconnect should return FAILURE_CLIENT_UNKNOWN + * when hotspot interface available. + */ +TEST_P(HostapdHidlTest, DisconnectClientWhenIfacAvailable) { + auto status_1_2 = + HIDL_INVOKE(hostapd_, addAccessPoint_1_3, getIfaceParamsWithoutAcs(), + getOpenNwParams()); + EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code); + + status_1_2 = + HIDL_INVOKE(hostapd_, forceClientDisconnect, getPrimaryWlanIfaceName(), + kTestZeroMacAddr, kTestDisconnectReasonCode); + EXPECT_EQ(HostapdStatusCode::FAILURE_CLIENT_UNKNOWN, status_1_2.code); +} + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HostapdHidlTest); +INSTANTIATE_TEST_CASE_P( + PerInstance, HostapdHidlTest, + testing::Combine( + testing::ValuesIn( + android::hardware::getAllHalInstanceNames(IWifi::descriptor)), + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + android::hardware::wifi::hostapd::V1_2::IHostapd::descriptor))), + android::hardware::PrintInstanceTupleNameToString<>);