1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Staache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <android-base/logging.h>
18
19#include <android/hardware/wifi/1.0/IWifiStaIface.h>
20
21#include <VtsHalHidlTargetTestBase.h>
22
23#include "wifi_hidl_call_util.h"
24#include "wifi_hidl_test_utils.h"
25
26using ::android::sp;
27using ::android::hardware::wifi::V1_0::Bssid;
28using ::android::hardware::wifi::V1_0::CommandId;
29using ::android::hardware::wifi::V1_0::IfaceType;
30using ::android::hardware::wifi::V1_0::IWifiStaIface;
31using ::android::hardware::wifi::V1_0::Rssi;
32using ::android::hardware::wifi::V1_0::Ssid;
33using ::android::hardware::wifi::V1_0::StaApfPacketFilterCapabilities;
34using ::android::hardware::wifi::V1_0::StaRoamingConfig;
35using ::android::hardware::wifi::V1_0::StaRoamingState;
36using ::android::hardware::wifi::V1_0::WifiBand;
37using ::android::hardware::wifi::V1_0::WifiStatus;
38using ::android::hardware::wifi::V1_0::WifiStatusCode;
39
40/**
41 * Fixture to use for all STA Iface HIDL interface tests.
42 */
43class WifiStaIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
44   public:
45    virtual void SetUp() override {
46        wifi_sta_iface_ = getWifiStaIface();
47        ASSERT_NE(nullptr, wifi_sta_iface_.get());
48    }
49
50    virtual void TearDown() override { stopWifi(); }
51
52   protected:
53    bool isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask cap_mask) {
54        const auto& status_and_caps =
55            HIDL_INVOKE(wifi_sta_iface_, getCapabilities);
56        EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
57        return (status_and_caps.second & cap_mask) != 0;
58    }
59
60    sp<IWifiStaIface> wifi_sta_iface_;
61};
62
63/*
64 * Create:
65 * Ensures that an instance of the IWifiStaIface proxy object is
66 * successfully created.
67 */
68TEST(WifiStaIfaceHidlTestNoFixture, Create) {
69    EXPECT_NE(nullptr, getWifiStaIface().get());
70    stopWifi();
71}
72
73/*
74 * GetCapabilities:
75 */
76TEST_F(WifiStaIfaceHidlTest, GetCapabilities) {
77    const auto& status_and_caps = HIDL_INVOKE(wifi_sta_iface_, getCapabilities);
78    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
79    EXPECT_GT(status_and_caps.second, 0u);
80}
81
82/*
83 * GetType:
84 * Ensures that the correct interface type is returned for station interface.
85 */
86TEST_F(WifiStaIfaceHidlTest, GetType) {
87    const auto& status_and_type = HIDL_INVOKE(wifi_sta_iface_, getType);
88    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_type.first.code);
89    EXPECT_EQ(IfaceType::STA, status_and_type.second);
90}
91
92/*
93 * GetApfPacketFilterCapabilities:
94 * Ensures that we can retrieve APF packet filter capabilites.
95 */
96TEST_F(WifiStaIfaceHidlTest, GetApfPacketFilterCapabilities) {
97    if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::APF)) {
98        // No-op if APF packet filer is not supported.
99        return;
100    }
101
102    const auto& status_and_caps =
103        HIDL_INVOKE(wifi_sta_iface_, getApfPacketFilterCapabilities);
104    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
105}
106
107/*
108 * GetBackgroundScanCapabilities:
109 * Ensures that we can retrieve background scan capabilities.
110 */
111TEST_F(WifiStaIfaceHidlTest, GetBackgroundScanCapabilities) {
112    if (!isCapabilitySupported(
113            IWifiStaIface::StaIfaceCapabilityMask::BACKGROUND_SCAN)) {
114        // No-op if background scan is not supported.
115        return;
116    }
117
118    const auto& status_and_caps =
119        HIDL_INVOKE(wifi_sta_iface_, getBackgroundScanCapabilities);
120    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
121}
122
123/*
124 * GetValidFrequenciesForBand:
125 * Ensures that we can retrieve valid frequencies for 2.4 GHz band.
126 */
127TEST_F(WifiStaIfaceHidlTest, GetValidFrequenciesForBand) {
128    const auto& status_and_freqs = HIDL_INVOKE(
129        wifi_sta_iface_, getValidFrequenciesForBand, WifiBand::BAND_24GHZ);
130    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_freqs.first.code);
131    EXPECT_GT(status_and_freqs.second.size(), 0u);
132}
133
134/*
135 * LinkLayerStatsCollection:
136 * Ensures that calls to enable, disable, and retrieve link layer stats
137 * will return a success status code.
138 */
139TEST_F(WifiStaIfaceHidlTest, LinkLayerStatsCollection) {
140    if (!isCapabilitySupported(
141            IWifiStaIface::StaIfaceCapabilityMask::LINK_LAYER_STATS)) {
142        // No-op if link layer stats is not supported.
143        return;
144    }
145
146    // Enable link layer stats collection.
147    EXPECT_EQ(WifiStatusCode::SUCCESS,
148              HIDL_INVOKE(wifi_sta_iface_, enableLinkLayerStatsCollection, true)
149                  .code);
150    // Retrieve link layer stats.
151    EXPECT_EQ(WifiStatusCode::SUCCESS,
152              HIDL_INVOKE(wifi_sta_iface_, getLinkLayerStats).first.code);
153    // Disable link layer stats collection.
154    EXPECT_EQ(
155        WifiStatusCode::SUCCESS,
156        HIDL_INVOKE(wifi_sta_iface_, disableLinkLayerStatsCollection).code);
157}
158
159/*
160 * RSSIMonitoring:
161 * Ensures that calls to enable RSSI monitoring will return an error status
162 * code if device is not connected to an AP.
163 * Ensures that calls to disable RSSI monitoring will return an error status
164 * code if RSSI monitoring is not enabled.
165 */
166TEST_F(WifiStaIfaceHidlTest, RSSIMonitoring) {
167    if (!isCapabilitySupported(
168            IWifiStaIface::StaIfaceCapabilityMask::RSSI_MONITOR)) {
169        // No-op if RSSI monitor is not supported.
170        return;
171    }
172
173    const CommandId kCmd = 1;
174    const Rssi kMaxRssi = -50;
175    const Rssi kMinRssi = -90;
176    // This is going to fail because device is not connected to an AP.
177    EXPECT_NE(WifiStatusCode::SUCCESS,
178              HIDL_INVOKE(wifi_sta_iface_, startRssiMonitoring, kCmd, kMaxRssi,
179                          kMinRssi)
180                  .code);
181    // This is going to fail because RSSI monitoring is not enabled.
182    EXPECT_NE(WifiStatusCode::SUCCESS,
183              HIDL_INVOKE(wifi_sta_iface_, stopRssiMonitoring, kCmd).code);
184}
185
186/*
187 * RoamingControl:
188 * Ensures that calls to configure and enable roaming will return a success
189 * status code.
190 */
191TEST_F(WifiStaIfaceHidlTest, RoamingControl) {
192    if (!isCapabilitySupported(
193            IWifiStaIface::StaIfaceCapabilityMask::CONTROL_ROAMING)) {
194        // No-op if roaming control is not supported.
195        return;
196    }
197
198    // Retrieve roaming capabilities.
199    const auto& status_and_cap =
200        HIDL_INVOKE(wifi_sta_iface_, getRoamingCapabilities);
201    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_cap.first.code);
202
203    // Setup roaming configuration based on roaming capabilities.
204    const auto& cap = status_and_cap.second;
205    StaRoamingConfig roaming_config;
206    if (cap.maxBlacklistSize > 0) {
207        Bssid black_list_bssid{
208            std::array<uint8_t, 6>{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}};
209        roaming_config.bssidBlacklist =
210            android::hardware::hidl_vec<Bssid>{black_list_bssid};
211    }
212    if (cap.maxWhitelistSize > 0) {
213        Ssid white_list_ssid{
214            std::array<uint8_t, 32>{{0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC}}};
215        roaming_config.ssidWhitelist =
216            android::hardware::hidl_vec<Ssid>{white_list_ssid};
217    }
218
219    // Configure roaming.
220    EXPECT_EQ(
221        WifiStatusCode::SUCCESS,
222        HIDL_INVOKE(wifi_sta_iface_, configureRoaming, roaming_config).code);
223
224    // Enable roaming.
225    EXPECT_EQ(
226        WifiStatusCode::SUCCESS,
227        HIDL_INVOKE(wifi_sta_iface_, setRoamingState, StaRoamingState::ENABLED)
228            .code);
229}
230
231/*
232 * EnableNDOffload:
233 * Ensures that calls to enable neighbor discovery offload will return a success
234 * status code.
235 */
236TEST_F(WifiStaIfaceHidlTest, EnableNDOffload) {
237   if (!isCapabilitySupported(
238           IWifiStaIface::StaIfaceCapabilityMask::ND_OFFLOAD)) {
239        // No-op if nd offload is not supported.
240        return;
241    }
242    EXPECT_EQ(WifiStatusCode::SUCCESS,
243              HIDL_INVOKE(wifi_sta_iface_, enableNdOffload, true).code);
244}
245
246/*
247 * SetScanningMacOui:
248 * Ensures that calls to set scanning MAC OUI will return a success status
249 * code.
250 */
251TEST_F(WifiStaIfaceHidlTest, SetScanningMacOui) {
252    const android::hardware::hidl_array<uint8_t, 3> kOui{
253        std::array<uint8_t, 3>{{0x10, 0x22, 0x33}}};
254    EXPECT_EQ(WifiStatusCode::SUCCESS,
255              HIDL_INVOKE(wifi_sta_iface_, setScanningMacOui, kOui).code);
256}
257
258/*
259 * PacketFateMonitoring:
260 * Ensures that calls to start packet fate monitoring and retrieve TX/RX
261 * packets will return a success status code.
262 */
263TEST_F(WifiStaIfaceHidlTest, PacketFateMonitoring) {
264   if (!isCapabilitySupported(
265           IWifiStaIface::StaIfaceCapabilityMask::DEBUG_PACKET_FATE)) {
266        // No-op if packet fate monitor is not supported.
267        return;
268    }
269    // Start packet fate monitoring.
270    EXPECT_EQ(
271        WifiStatusCode::SUCCESS,
272        HIDL_INVOKE(wifi_sta_iface_, startDebugPacketFateMonitoring).code);
273
274    // Retrieve packets.
275    EXPECT_EQ(WifiStatusCode::SUCCESS,
276              HIDL_INVOKE(wifi_sta_iface_, getDebugTxPacketFates).first.code);
277    EXPECT_EQ(WifiStatusCode::SUCCESS,
278              HIDL_INVOKE(wifi_sta_iface_, getDebugRxPacketFates).first.code);
279}
280