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

Commit 5fba090f authored by Roshan Pius's avatar Roshan Pius
Browse files

hostapd(vts): VTS tests for the HIDL interface

Bug: 36646171
Bug: 71613528
Test: `adb shell /data/VtsHalWifiHostapdV1_0TargetTest`
Change-Id: I979296be7d97c6768c4fb76586025109758261ef
parent e6a8a00f
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
//
// Copyright (C) 2018 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_library_static {
    name: "VtsHalWifiHostapdV1_0TargetTestUtil",
    defaults: ["VtsHalTargetTestDefaults"],
    srcs: ["hostapd_hidl_test_utils.cpp"],
    export_include_dirs: [
        "."
    ],
    static_libs: [
        "VtsHalWifiV1_0TargetTestUtil",
        "android.hardware.wifi.hostapd@1.0",
        "android.hardware.wifi@1.0",
        "libcrypto",
        "libgmock",
        "libwifi-system",
        "libwifi-system-iface",
    ],
}

cc_test {
    name: "VtsHalWifiHostapdV1_0TargetTest",
    defaults: ["VtsHalTargetTestDefaults"],
    srcs: [
        "VtsHalWifiHostapdV1_0TargetTest.cpp",
        "hostapd_hidl_test.cpp",
    ],
    static_libs: [
        "VtsHalWifiV1_0TargetTestUtil",
        "VtsHalWifiHostapdV1_0TargetTestUtil",
        "android.hardware.wifi.hostapd@1.0",
        "android.hardware.wifi@1.0",
        "libcrypto",
        "libgmock",
        "libwifi-system",
        "libwifi-system-iface",
    ],
}
+35 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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 <android-base/logging.h>

#include <VtsHalHidlTargetTestBase.h>

#include "hostapd_hidl_test_utils.h"

class HostapdHidlEnvironment : public ::testing::Environment {
   public:
    virtual void SetUp() override { stopHostapd(); }
    virtual void TearDown() override { startHostapdAndWaitForHidlService(); }
};

int main(int argc, char** argv) {
    ::testing::AddGlobalTestEnvironment(new HostapdHidlEnvironment);
    ::testing::InitGoogleTest(&argc, argv);
    int status = RUN_ALL_TESTS();
    LOG(INFO) << "Test result = " << status;
    return status;
}
+127 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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 copied from
// hardware/interfaces/wifi/1.0/vts/functional/wifi_hidl_call_util.h
// Please make sure these two file are consistent.

#pragma once

#include <functional>
#include <tuple>
#include <type_traits>
#include <utility>

#include <VtsHalHidlTargetTestBase.h>

namespace {
namespace detail {
template <typename>
struct functionArgSaver;

// Provides a std::function that takes one argument, and a buffer
// wherein the function will store its argument. The buffer has
// the same type as the argument, but with const and reference
// modifiers removed.
template <typename ArgT>
struct functionArgSaver<std::function<void(ArgT)>> final {
    using StorageT = typename std::remove_const<
        typename std::remove_reference<ArgT>::type>::type;

    std::function<void(ArgT)> saveArgs = [this](ArgT arg) {
        this->saved_values = arg;
    };

    StorageT saved_values;
};

// Provides a std::function that takes two arguments, and a buffer
// wherein the function will store its arguments. The buffer is a
// std::pair, whose elements have the same types as the arguments
// (but with const and reference modifiers removed).
template <typename Arg1T, typename Arg2T>
struct functionArgSaver<std::function<void(Arg1T, Arg2T)>> final {
    using StorageT =
        std::pair<typename std::remove_const<
                      typename std::remove_reference<Arg1T>::type>::type,
                  typename std::remove_const<
                      typename std::remove_reference<Arg2T>::type>::type>;

    std::function<void(Arg1T, Arg2T)> saveArgs = [this](Arg1T arg1,
                                                        Arg2T arg2) {
        this->saved_values = {arg1, arg2};
    };

    StorageT saved_values;
};

// Provides a std::function that takes three or more arguments, and a
// buffer wherein the function will store its arguments. The buffer is a
// std::tuple whose elements have the same types as the arguments (but
// with const and reference modifiers removed).
template <typename... ArgT>
struct functionArgSaver<std::function<void(ArgT...)>> final {
    using StorageT = std::tuple<typename std::remove_const<
        typename std::remove_reference<ArgT>::type>::type...>;

    std::function<void(ArgT...)> saveArgs = [this](ArgT... arg) {
        this->saved_values = {arg...};
    };

    StorageT saved_values;
};

// Invokes |method| on |object|, providing |method| a CallbackT as the
// final argument. Returns a copy of the parameters that |method| provided
// to CallbackT. (The parameters are returned by value.)
template <typename CallbackT, typename MethodT, typename ObjectT,
          typename... ArgT>
typename functionArgSaver<CallbackT>::StorageT invokeMethod(
    MethodT method, ObjectT object, ArgT&&... methodArg) {
    functionArgSaver<CallbackT> result_buffer;
    const auto& res = ((*object).*method)(std::forward<ArgT>(methodArg)...,
                                          result_buffer.saveArgs);
    EXPECT_TRUE(res.isOk());
    return result_buffer.saved_values;
}
}  // namespace detail
}  // namespace

// Invokes |method| on |strong_pointer|, passing provided arguments through to
// |method|.
//
// Returns either:
// - A copy of the result callback parameter (for callbacks with a single
//   parameter), OR
// - A pair containing a copy of the result callback parameters (for callbacks
//   with two parameters), OR
// - A tuple containing a copy of the result callback paramters (for callbacks
//   with three or more parameters).
//
// Example usage:
//   EXPECT_EQ(HostapdStatusCode::SUCCESS,
//       HIDL_INVOKE(strong_pointer, methodReturningHostapdStatus).code);
//   EXPECT_EQ(HostapdStatusCode::SUCCESS,
//       HIDL_INVOKE(strong_pointer, methodReturningHostapdStatusAndOneMore)
//         .first.code);
//   EXPECT_EQ(HostapdStatusCode::SUCCESS, std::get<0>(
//       HIDL_INVOKE(strong_pointer, methodReturningHostapdStatusAndTwoMore))
//         .code);
#define HIDL_INVOKE(strong_pointer, method, ...)                              \
    (detail::invokeMethod<                                                    \
        std::remove_reference<decltype(*strong_pointer)>::type::method##_cb>( \
        &std::remove_reference<decltype(*strong_pointer)>::type::method,      \
        strong_pointer, ##__VA_ARGS__))
+222 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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 <android-base/logging.h>
#include <cutils/properties.h>

#include <VtsHalHidlTargetTestBase.h>

#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>

#include "hostapd_hidl_call_util.h"
#include "hostapd_hidl_test_utils.h"

using ::android::sp;
using ::android::hardware::hidl_vec;
using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
using ::android::hardware::wifi::hostapd::V1_0::HostapdStatus;
using ::android::hardware::wifi::hostapd::V1_0::HostapdStatusCode;

namespace {
constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1',
                                     '2', '3', '4', '5'};
constexpr char kNwPassphrase[] = "test12345";
constexpr int kIfaceChannel = 6;
constexpr int kIfaceInvalidChannel = 567;
}  // namespace

class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase {
   public:
    virtual void SetUp() override {
        startHostapdAndWaitForHidlService();
        hostapd_ = getHostapd();
        ASSERT_NE(hostapd_.get(), nullptr);
    }

    virtual void TearDown() override { stopHostapd(); }

   protected:
    std::string getPrimaryWlanIfaceName() {
        std::array<char, PROPERTY_VALUE_MAX> buffer;
        property_get("wifi.interface", buffer.data(), "wlan0");
        return buffer.data();
    }

    IHostapd::IfaceParams getIfaceParamsWithAcs() {
        IHostapd::IfaceParams iface_params;
        iface_params.ifaceName = getPrimaryWlanIfaceName();
        iface_params.hwModeParams.enable80211N = true;
        iface_params.hwModeParams.enable80211AC = false;
        iface_params.channelParams.enableAcs = true;
        iface_params.channelParams.acsShouldExcludeDfs = true;
        iface_params.channelParams.channel = 0;
        iface_params.channelParams.band = IHostapd::Band::BAND_ANY;
        return iface_params;
    }

    IHostapd::IfaceParams getIfaceParamsWithoutAcs() {
        IHostapd::IfaceParams iface_params;
        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.channelParams.band = IHostapd::Band::BAND_2_4_GHZ;
        return iface_params;
    }

    IHostapd::IfaceParams getIfaceParamsWithInvalidChannel() {
        IHostapd::IfaceParams iface_params;
        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 = kIfaceInvalidChannel;
        iface_params.channelParams.band = IHostapd::Band::BAND_2_4_GHZ;
        return iface_params;
    }

    IHostapd::NetworkParams getPskNwParams() {
        IHostapd::NetworkParams nw_params;
        nw_params.ssid =
            std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
        nw_params.isHidden = false;
        nw_params.encryptionType = IHostapd::EncryptionType::WPA2;
        nw_params.pskPassphrase = kNwPassphrase;
        return nw_params;
    }

    IHostapd::NetworkParams getInvalidPskNwParams() {
        IHostapd::NetworkParams nw_params;
        nw_params.ssid =
            std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
        nw_params.isHidden = false;
        nw_params.encryptionType = IHostapd::EncryptionType::WPA2;
        return nw_params;
    }

    IHostapd::NetworkParams getOpenNwParams() {
        IHostapd::NetworkParams nw_params;
        nw_params.ssid =
            std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
        nw_params.isHidden = false;
        nw_params.encryptionType = IHostapd::EncryptionType::NONE;
        return nw_params;
    }
    // IHostapd object used for all tests in this fixture.
    sp<IHostapd> hostapd_;
};

/*
 * Create:
 * Ensures that an instance of the IHostapd proxy object is
 * successfully created.
 */
TEST(HostapdHidlTestNoFixture, Create) {
    startHostapdAndWaitForHidlService();
    EXPECT_NE(nullptr, getHostapd().get());
    stopHostapd();
}

/**
 * Adds an access point with PSK network config & ACS enabled.
 * Access point creation should pass.
 */
TEST_F(HostapdHidlTest, AddPskAccessPointWithAcs) {
    auto status = HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithAcs(),
                              getPskNwParams());
    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
}

/**
 * Adds an access point with Open network config & ACS enabled.
 * Access point creation should pass.
 */
TEST_F(HostapdHidlTest, AddOpenAccessPointWithAcs) {
    auto status = HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithAcs(),
                              getOpenNwParams());
    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
}

/**
 * Adds an access point with PSK network config & ACS disabled.
 * Access point creation should pass.
 */
TEST_F(HostapdHidlTest, AddPskAccessPointWithoutAcs) {
    auto status = HIDL_INVOKE(hostapd_, addAccessPoint,
                              getIfaceParamsWithoutAcs(), getPskNwParams());
    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
}

/**
 * Adds an access point with Open network config & ACS disabled.
 * Access point creation should pass.
 */
TEST_F(HostapdHidlTest, AddOpenAccessPointWithoutAcs) {
    auto status = HIDL_INVOKE(hostapd_, addAccessPoint,
                              getIfaceParamsWithoutAcs(), getOpenNwParams());
    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_F(HostapdHidlTest, RemoveAccessPointWithAcs) {
    auto status = HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithAcs(),
                              getPskNwParams());
    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
    status =
        HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
}

/**
 * Adds & then removes an access point with PSK network config & ACS disabled.
 * Access point creation & removal should pass.
 */
TEST_F(HostapdHidlTest, RemoveAccessPointWithoutAcs) {
    auto status = HIDL_INVOKE(hostapd_, addAccessPoint,
                              getIfaceParamsWithoutAcs(), getPskNwParams());
    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
    status =
        HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
    EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
}

/**
 * Adds an access point with invalid channel.
 * Access point creation should fail.
 */
TEST_F(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) {
    auto status =
        HIDL_INVOKE(hostapd_, addAccessPoint,
                    getIfaceParamsWithInvalidChannel(), getPskNwParams());
    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
}

/**
 * Adds an access point with invalid PSK network config.
 * Access point creation should fail.
 */
TEST_F(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) {
    auto status =
        HIDL_INVOKE(hostapd_, addAccessPoint, getIfaceParamsWithoutAcs(),
                    getInvalidPskNwParams());
    EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
}
+135 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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 <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>

#include <android/hidl/manager/1.0/IServiceManager.h>
#include <android/hidl/manager/1.0/IServiceNotification.h>
#include <hidl/HidlTransportSupport.h>

#include <wifi_system/hostapd_manager.h>
#include <wifi_system/interface_tool.h>

#include "hostapd_hidl_test_utils.h"
#include "wifi_hidl_test_utils.h"

using ::android::sp;
using ::android::hardware::configureRpcThreadpool;
using ::android::hardware::joinRpcThreadpool;
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::IWifiChip;
using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
using ::android::hardware::wifi::hostapd::V1_0::HostapdStatus;
using ::android::hardware::wifi::hostapd::V1_0::HostapdStatusCode;
using ::android::hidl::manager::V1_0::IServiceNotification;
using ::android::wifi_system::HostapdManager;

namespace {
const char kHostapdServiceName[] = "default";

// Helper function to initialize the driver and firmware to AP mode
// using the vendor HAL HIDL interface.
void initilializeDriverAndFirmware() {
    sp<IWifiChip> wifi_chip = getWifiChip();
    ChipModeId mode_id;
    EXPECT_TRUE(configureChipToSupportIfaceType(
        wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::AP, &mode_id));
}

// Helper function to deinitialize the driver and firmware
// using the vendor HAL HIDL interface.
void deInitilializeDriverAndFirmware() { stopWifi(); }
}  // namespace

// Utility class to wait for wpa_hostapd's HIDL service registration.
class ServiceNotificationListener : public IServiceNotification {
   public:
    Return<void> onRegistration(const hidl_string& fully_qualified_name,
                                const hidl_string& instance_name,
                                bool pre_existing) override {
        if (pre_existing) {
            return Void();
        }
        std::unique_lock<std::mutex> lock(mutex_);
        registered_.push_back(std::string(fully_qualified_name.c_str()) + "/" +
                              instance_name.c_str());
        lock.unlock();
        condition_.notify_one();
        return Void();
    }

    bool registerForHidlServiceNotifications(const std::string& instance_name) {
        if (!IHostapd::registerForNotifications(instance_name, this)) {
            return false;
        }
        configureRpcThreadpool(2, false);
        return true;
    }

    bool waitForHidlService(uint32_t timeout_in_millis,
                            const std::string& instance_name) {
        std::unique_lock<std::mutex> lock(mutex_);
        condition_.wait_for(lock, std::chrono::milliseconds(timeout_in_millis),
                            [&]() { return registered_.size() >= 1; });
        if (registered_.size() != 1) {
            return false;
        }
        std::string expected_registered =
            std::string(IHostapd::descriptor) + "/" + instance_name;
        if (registered_[0] != expected_registered) {
            LOG(ERROR) << "Expected: " << expected_registered
                       << ", Got: " << registered_[0];
            return false;
        }
        return true;
    }

   private:
    std::vector<std::string> registered_{};
    std::mutex mutex_;
    std::condition_variable condition_;
};

void stopHostapd() {
    HostapdManager hostapd_manager;

    ASSERT_TRUE(hostapd_manager.StopHostapd());
    deInitilializeDriverAndFirmware();
}

void startHostapdAndWaitForHidlService() {
    initilializeDriverAndFirmware();

    android::sp<ServiceNotificationListener> notification_listener =
        new ServiceNotificationListener();
    ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications(
        kHostapdServiceName));

    HostapdManager hostapd_manager;
    ASSERT_TRUE(hostapd_manager.StartHostapd());

    ASSERT_TRUE(
        notification_listener->waitForHidlService(200, kHostapdServiceName));
}

sp<IHostapd> getHostapd() {
    return ::testing::VtsHalHidlTargetTestBase::getService<IHostapd>();
}
Loading