blob: d6c750f6c7dfca3f68c53b6c6aa70dbef96112af [file] [log] [blame]
/*
* 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 <VtsCoreUtil.h>
#include <android-base/logging.h>
#include <cutils/properties.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
#include <android/hardware/wifi/1.0/IWifi.h>
#include <android/hardware/wifi/hostapd/1.3/IHostapd.h>
#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<std::tuple<std::string, std::string>> {
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<char, PROPERTY_VALUE_MAX> 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<uint8_t>(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<IHostapd> 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<>);