• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache 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 #include <aidl/android/hardware/wifi/IWifi.h>
17 #include <android/hardware/wifi/1.0/IWifi.h>
18 #include <android/hardware/wifi/hostapd/1.3/IHostapd.h>
19 
20 #include <VtsCoreUtil.h>
21 #include <aidl/Gtest.h>
22 #include <aidl/Vintf.h>
23 #include <aidl/android/hardware/wifi/hostapd/BnHostapd.h>
24 #include <aidl/android/hardware/wifi/hostapd/BnHostapdCallback.h>
25 #include <android/binder_manager.h>
26 #include <binder/IServiceManager.h>
27 #include <binder/ProcessState.h>
28 #include <hidl/ServiceManagement.h>
29 #include <hostapd_hidl_call_util.h>
30 #include <hostapd_hidl_test_utils.h>
31 #include <wifi_hidl_test_utils.h>
32 #include <wifi_hidl_test_utils_1_5.h>
33 #include <wifi_hidl_test_utils_1_6.h>
34 
35 #include "hostapd_test_utils.h"
36 #include "wifi_aidl_test_utils.h"
37 
38 using aidl::android::hardware::wifi::hostapd::BandMask;
39 using aidl::android::hardware::wifi::hostapd::BnHostapdCallback;
40 using aidl::android::hardware::wifi::hostapd::ChannelBandwidth;
41 using aidl::android::hardware::wifi::hostapd::ChannelParams;
42 using aidl::android::hardware::wifi::hostapd::DebugLevel;
43 using aidl::android::hardware::wifi::hostapd::EncryptionType;
44 using aidl::android::hardware::wifi::hostapd::FrequencyRange;
45 using aidl::android::hardware::wifi::hostapd::Ieee80211ReasonCode;
46 using aidl::android::hardware::wifi::hostapd::IfaceParams;
47 using aidl::android::hardware::wifi::hostapd::IHostapd;
48 using aidl::android::hardware::wifi::hostapd::NetworkParams;
49 using android::ProcessState;
50 
51 namespace {
52 const unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1', '2', '3', '4', '5'};
53 const std::string kPassphrase = "test12345";
54 const std::string kInvalidMinPassphrase = "test";
55 const std::string kInvalidMaxPassphrase =
56     "0123456789012345678901234567890123456789012345678901234567890123456789";
57 const int kIfaceChannel = 6;
58 const int kIfaceInvalidChannel = 567;
59 const std::vector<uint8_t> kTestZeroMacAddr(6, 0x0);
60 const Ieee80211ReasonCode kTestDisconnectReasonCode = Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED;
61 const auto& kTestVendorDataOptional = generateOuiKeyedDataListOptional(5);
62 
operator |(BandMask a,BandMask b)63 inline BandMask operator|(BandMask a, BandMask b) {
64     return static_cast<BandMask>(static_cast<int32_t>(a) |
65                                  static_cast<int32_t>(b));
66 }
67 }  // namespace
68 
69 class HostapdAidl : public testing::TestWithParam<std::string> {
70    public:
SetUp()71     virtual void SetUp() override {
72         disableHalsAndFramework();
73         initializeHostapdAndVendorHal(GetParam());
74 
75         hostapd = getHostapd(GetParam());
76         ASSERT_NE(hostapd, nullptr);
77         EXPECT_TRUE(hostapd->setDebugParams(DebugLevel::EXCESSIVE).isOk());
78         EXPECT_TRUE(hostapd->getInterfaceVersion(&interface_version_).isOk());
79 
80         isAcsSupport = testing::checkSubstringInCommandOutput(
81             "/system/bin/cmd wifi get-softap-supported-features",
82             "wifi_softap_acs_supported");
83         isWpa3SaeSupport = testing::checkSubstringInCommandOutput(
84             "/system/bin/cmd wifi get-softap-supported-features",
85             "wifi_softap_wpa3_sae_supported");
86         isBridgedSupport = testing::checkSubstringInCommandOutput(
87                 "/system/bin/cmd wifi get-softap-supported-features",
88                 "wifi_softap_bridged_ap_supported");
89         isMloSupport = testing::checkSubstringInCommandOutput(
90                 "/system/bin/cmd wifi get-softap-supported-features", "wifi_softap_mlo_supported");
91     }
92 
TearDown()93     virtual void TearDown() override {
94         hostapd->terminate();
95         //  Wait 3 seconds to allow terminate to complete
96         sleep(3);
97         stopHostapdAndVendorHal();
98         startWifiFramework();
99     }
100 
101     std::shared_ptr<IHostapd> hostapd;
102     bool isAcsSupport;
103     bool isWpa3SaeSupport;
104     bool isBridgedSupport;
105     bool isMloSupport;
106     int interface_version_;
107 
getIfaceParamsWithoutAcs(std::string iface_name)108     IfaceParams getIfaceParamsWithoutAcs(std::string iface_name) {
109         IfaceParams iface_params;
110         ChannelParams channelParams;
111         std::vector<ChannelParams> vec_channelParams;
112 
113         iface_params.name = iface_name;
114         iface_params.hwModeParams.enable80211N = true;
115         iface_params.hwModeParams.enable80211AC = false;
116         iface_params.hwModeParams.enable80211AX = false;
117         iface_params.hwModeParams.enable6GhzBand = false;
118         iface_params.hwModeParams.maximumChannelBandwidth = ChannelBandwidth::BANDWIDTH_20;
119 
120         channelParams.enableAcs = false;
121         channelParams.acsShouldExcludeDfs = false;
122         channelParams.channel = kIfaceChannel;
123         channelParams.bandMask = BandMask::BAND_2_GHZ;
124 
125         vec_channelParams.push_back(channelParams);
126         iface_params.channelParams = vec_channelParams;
127         return iface_params;
128     }
129 
getIfaceParamsWithBridgedModeACS(std::string iface_name)130     IfaceParams getIfaceParamsWithBridgedModeACS(std::string iface_name) {
131         IfaceParams iface_params = getIfaceParamsWithoutAcs(iface_name);
132         iface_params.channelParams[0].enableAcs = true;
133         iface_params.channelParams[0].acsShouldExcludeDfs = true;
134 
135         std::vector<ChannelParams> vec_channelParams;
136         vec_channelParams.push_back(iface_params.channelParams[0]);
137 
138         ChannelParams second_channelParams;
139         second_channelParams.channel = 0;
140         second_channelParams.enableAcs = true;
141         second_channelParams.bandMask = BandMask::BAND_5_GHZ;
142         vec_channelParams.push_back(second_channelParams);
143 
144         iface_params.channelParams = vec_channelParams;
145         return iface_params;
146     }
147 
getIfaceParamsWithAcs(std::string iface_name)148     IfaceParams getIfaceParamsWithAcs(std::string iface_name) {
149         IfaceParams iface_params = getIfaceParamsWithoutAcs(iface_name);
150         iface_params.channelParams[0].enableAcs = true;
151         iface_params.channelParams[0].acsShouldExcludeDfs = true;
152         iface_params.channelParams[0].channel = 0;
153         iface_params.channelParams[0].bandMask =
154             iface_params.channelParams[0].bandMask | BandMask::BAND_5_GHZ;
155         return iface_params;
156     }
157 
getIfaceParamsWithAcsAndFreqRange(std::string iface_name)158     IfaceParams getIfaceParamsWithAcsAndFreqRange(std::string iface_name) {
159         IfaceParams iface_params = getIfaceParamsWithAcs(iface_name);
160         FrequencyRange freqRange;
161         freqRange.startMhz = 2412;
162         freqRange.endMhz = 2462;
163         std::vector<FrequencyRange> vec_FrequencyRange;
164         vec_FrequencyRange.push_back(freqRange);
165         iface_params.channelParams[0].acsChannelFreqRangesMhz =
166             vec_FrequencyRange;
167         return iface_params;
168     }
169 
getIfaceParamsWithAcsAndInvalidFreqRange(std::string iface_name)170     IfaceParams getIfaceParamsWithAcsAndInvalidFreqRange(
171         std::string iface_name) {
172         IfaceParams iface_params =
173             getIfaceParamsWithAcsAndFreqRange(iface_name);
174         iface_params.channelParams[0].acsChannelFreqRangesMhz[0].startMhz =
175             222;
176         iface_params.channelParams[0].acsChannelFreqRangesMhz[0].endMhz =
177             999;
178         return iface_params;
179     }
180 
getIfaceParamsWithInvalidChannel(std::string iface_name)181     IfaceParams getIfaceParamsWithInvalidChannel(std::string iface_name) {
182         IfaceParams iface_params = getIfaceParamsWithoutAcs(iface_name);
183         iface_params.channelParams[0].channel = kIfaceInvalidChannel;
184         return iface_params;
185     }
186 
getOpenNwParams()187     NetworkParams getOpenNwParams() {
188         NetworkParams nw_params;
189         nw_params.ssid =
190             std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
191         nw_params.isHidden = false;
192         nw_params.encryptionType = EncryptionType::NONE;
193         nw_params.isMetered = true;
194         return nw_params;
195     }
196 
getPskNwParamsWithNonMetered()197     NetworkParams getPskNwParamsWithNonMetered() {
198         NetworkParams nw_params = getOpenNwParams();
199         nw_params.encryptionType = EncryptionType::WPA2;
200         nw_params.passphrase = kPassphrase;
201         nw_params.isMetered = false;
202         return nw_params;
203     }
204 
getPskNwParams()205     NetworkParams getPskNwParams() {
206         NetworkParams nw_params = getOpenNwParams();
207         nw_params.encryptionType = EncryptionType::WPA2;
208         nw_params.passphrase = kPassphrase;
209         return nw_params;
210     }
211 
getInvalidPskNwParams()212     NetworkParams getInvalidPskNwParams() {
213         NetworkParams nw_params = getOpenNwParams();
214         nw_params.encryptionType = EncryptionType::WPA2;
215         nw_params.passphrase = kInvalidMaxPassphrase;
216         return nw_params;
217     }
218 
getSaeTransitionNwParams()219     NetworkParams getSaeTransitionNwParams() {
220         NetworkParams nw_params = getOpenNwParams();
221         nw_params.encryptionType = EncryptionType::WPA3_SAE_TRANSITION;
222         nw_params.passphrase = kPassphrase;
223         return nw_params;
224     }
225 
getInvalidSaeTransitionNwParams()226     NetworkParams getInvalidSaeTransitionNwParams() {
227         NetworkParams nw_params = getOpenNwParams();
228         nw_params.encryptionType = EncryptionType::WPA2;
229         nw_params.passphrase = kInvalidMinPassphrase;
230         return nw_params;
231     }
232 
getSaeNwParams()233     NetworkParams getSaeNwParams() {
234         NetworkParams nw_params = getOpenNwParams();
235         nw_params.encryptionType = EncryptionType::WPA3_SAE;
236         nw_params.passphrase = kPassphrase;
237         return nw_params;
238     }
239 
getInvalidSaeNwParams()240     NetworkParams getInvalidSaeNwParams() {
241         NetworkParams nw_params = getOpenNwParams();
242         nw_params.encryptionType = EncryptionType::WPA3_SAE;
243         nw_params.passphrase = "";
244         return nw_params;
245     }
246 };
247 
248 class HostapdCallback : public BnHostapdCallback {
249    public:
250     HostapdCallback() = default;
onApInstanceInfoChanged(const::aidl::android::hardware::wifi::hostapd::ApInfo &)251     ::ndk::ScopedAStatus onApInstanceInfoChanged(
252         const ::aidl::android::hardware::wifi::hostapd::ApInfo &) override {
253         return ndk::ScopedAStatus::ok();
254     }
onConnectedClientsChanged(const::aidl::android::hardware::wifi::hostapd::ClientInfo &)255     ::ndk::ScopedAStatus onConnectedClientsChanged(
256         const ::aidl::android::hardware::wifi::hostapd::ClientInfo &) override {
257         return ndk::ScopedAStatus::ok();
258     }
onFailure(const std::string &,const std::string &)259     ::ndk::ScopedAStatus onFailure(const std::string&, const std::string&) override {
260         return ndk::ScopedAStatus::ok();
261     }
262 };
263 
264 /**
265  * Register callback
266  */
TEST_P(HostapdAidl,RegisterCallback)267 TEST_P(HostapdAidl, RegisterCallback) {
268     std::shared_ptr<HostapdCallback> callback =
269         ndk::SharedRefBase::make<HostapdCallback>();
270     ASSERT_NE(callback, nullptr);
271     EXPECT_TRUE(hostapd->registerCallback(callback).isOk());
272 }
273 
274 /**
275  * Adds an access point with PSK network config & ACS enabled.
276  * Access point creation should pass.
277  */
TEST_P(HostapdAidl,AddPskAccessPointWithAcs)278 TEST_P(HostapdAidl, AddPskAccessPointWithAcs) {
279     if (!isAcsSupport) GTEST_SKIP() << "Missing ACS support";
280     std::string ifname = setupApIfaceAndGetName(false);
281     auto status = hostapd->addAccessPoint(getIfaceParamsWithAcs(ifname), getPskNwParams());
282     EXPECT_TRUE(status.isOk());
283 }
284 
285 /**
286  * Adds an access point with PSK network config, ACS enabled & frequency Range.
287  * Access point creation should pass.
288  */
TEST_P(HostapdAidl,AddPskAccessPointWithAcsAndFreqRange)289 TEST_P(HostapdAidl, AddPskAccessPointWithAcsAndFreqRange) {
290     if (!isAcsSupport) GTEST_SKIP() << "Missing ACS support";
291     std::string ifname = setupApIfaceAndGetName(false);
292     auto status =
293             hostapd->addAccessPoint(getIfaceParamsWithAcsAndFreqRange(ifname), getPskNwParams());
294     EXPECT_TRUE(status.isOk());
295 }
296 
297 /**
298  * Adds an access point with invalid channel range.
299  * Access point creation should fail.
300  */
TEST_P(HostapdAidl,AddPskAccessPointWithAcsAndInvalidFreqRange)301 TEST_P(HostapdAidl, AddPskAccessPointWithAcsAndInvalidFreqRange) {
302     if (!isAcsSupport) GTEST_SKIP() << "Missing ACS support";
303     std::string ifname = setupApIfaceAndGetName(false);
304     auto status = hostapd->addAccessPoint(getIfaceParamsWithAcsAndInvalidFreqRange(ifname),
305                                           getPskNwParams());
306     EXPECT_FALSE(status.isOk());
307 }
308 
309 /**
310  * Adds an access point with Open network config & ACS enabled.
311  * Access point creation should pass.
312  */
TEST_P(HostapdAidl,AddOpenAccessPointWithAcs)313 TEST_P(HostapdAidl, AddOpenAccessPointWithAcs) {
314     if (!isAcsSupport) GTEST_SKIP() << "Missing ACS support";
315     std::string ifname = setupApIfaceAndGetName(false);
316     auto status = hostapd->addAccessPoint(getIfaceParamsWithAcs(ifname), getOpenNwParams());
317     EXPECT_TRUE(status.isOk());
318 }
319 
320 /**
321  * Adds an access point with PSK network config & ACS disabled.
322  * Access point creation should pass.
323  */
TEST_P(HostapdAidl,AddPskAccessPointWithoutAcs)324 TEST_P(HostapdAidl, AddPskAccessPointWithoutAcs) {
325     std::string ifname = setupApIfaceAndGetName(false);
326     auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(ifname), getPskNwParams());
327     EXPECT_TRUE(status.isOk());
328 }
329 
330 /**
331  * Adds an access point with PSK network config, ACS disabled & Non metered.
332  * Access point creation should pass.
333  */
TEST_P(HostapdAidl,AddPskAccessPointWithoutAcsAndNonMetered)334 TEST_P(HostapdAidl, AddPskAccessPointWithoutAcsAndNonMetered) {
335     std::string ifname = setupApIfaceAndGetName(false);
336     auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(ifname),
337                                           getPskNwParamsWithNonMetered());
338     EXPECT_TRUE(status.isOk());
339 }
340 
341 /**
342  * Adds an access point with Open network config & ACS disabled.
343  * Access point creation should pass.
344  */
TEST_P(HostapdAidl,AddOpenAccessPointWithoutAcs)345 TEST_P(HostapdAidl, AddOpenAccessPointWithoutAcs) {
346     std::string ifname = setupApIfaceAndGetName(false);
347     auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(ifname), getOpenNwParams());
348     EXPECT_TRUE(status.isOk());
349 }
350 
351 /**
352  * Adds an access point with Open network config & ACS disabled.
353  * IfaceParams will also include vendor data.
354  * Access point creation should pass.
355  */
TEST_P(HostapdAidl,AddOpenAccessPointWithVendorData)356 TEST_P(HostapdAidl, AddOpenAccessPointWithVendorData) {
357     if (interface_version_ < 2) {
358         GTEST_SKIP() << "Vendor data is available in IfaceParams as of Hostapd V2";
359     }
360     std::string ifname = setupApIfaceAndGetName(false);
361     IfaceParams params = getIfaceParamsWithoutAcs(ifname);
362     params.vendorData = kTestVendorDataOptional;
363     auto status = hostapd->addAccessPoint(params, getOpenNwParams());
364     EXPECT_TRUE(status.isOk());
365 }
366 
367 /**
368  * Adds an access point with SAE Transition network config & ACS disabled.
369  * Access point creation should pass.
370  */
TEST_P(HostapdAidl,AddSaeTransitionAccessPointWithoutAcs)371 TEST_P(HostapdAidl, AddSaeTransitionAccessPointWithoutAcs) {
372     if (!isWpa3SaeSupport) GTEST_SKIP() << "Missing SAE support";
373     std::string ifname = setupApIfaceAndGetName(false);
374     auto status =
375             hostapd->addAccessPoint(getIfaceParamsWithoutAcs(ifname), getSaeTransitionNwParams());
376     EXPECT_TRUE(status.isOk());
377 }
378 
379 /**
380  * Adds an access point with SAE network config & ACS disabled.
381  * Access point creation should pass.
382  */
TEST_P(HostapdAidl,AddSAEAccessPointWithoutAcs)383 TEST_P(HostapdAidl, AddSAEAccessPointWithoutAcs) {
384     if (!isWpa3SaeSupport) GTEST_SKIP() << "Missing SAE support";
385     std::string ifname = setupApIfaceAndGetName(false);
386     auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(ifname), getSaeNwParams());
387     EXPECT_TRUE(status.isOk());
388 }
389 
390 /**
391  * Adds & then removes an access point with PSK network config & ACS enabled.
392  * Access point creation & removal should pass.
393  */
TEST_P(HostapdAidl,RemoveAccessPointWithAcs)394 TEST_P(HostapdAidl, RemoveAccessPointWithAcs) {
395     if (!isAcsSupport) GTEST_SKIP() << "Missing ACS support";
396     std::string ifname = setupApIfaceAndGetName(false);
397     auto status = hostapd->addAccessPoint(getIfaceParamsWithAcs(ifname), getPskNwParams());
398     EXPECT_TRUE(status.isOk());
399     EXPECT_TRUE(hostapd->removeAccessPoint(ifname).isOk());
400 }
401 
402 /**
403  * Adds & then removes an access point with PSK network config & ACS disabled.
404  * Access point creation & removal should pass.
405  */
TEST_P(HostapdAidl,RemoveAccessPointWithoutAcs)406 TEST_P(HostapdAidl, RemoveAccessPointWithoutAcs) {
407     std::string ifname = setupApIfaceAndGetName(false);
408     auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(ifname), getPskNwParams());
409     EXPECT_TRUE(status.isOk());
410     EXPECT_TRUE(hostapd->removeAccessPoint(ifname).isOk());
411 }
412 
413 /**
414  * Adds an access point with invalid channel.
415  * Access point creation should fail.
416  */
TEST_P(HostapdAidl,AddPskAccessPointWithInvalidChannel)417 TEST_P(HostapdAidl, AddPskAccessPointWithInvalidChannel) {
418     std::string ifname = setupApIfaceAndGetName(false);
419     auto status =
420             hostapd->addAccessPoint(getIfaceParamsWithInvalidChannel(ifname), getPskNwParams());
421     EXPECT_FALSE(status.isOk());
422 }
423 
424 /**
425  * Adds an access point with invalid PSK network config.
426  * Access point creation should fail.
427  */
TEST_P(HostapdAidl,AddInvalidPskAccessPointWithoutAcs)428 TEST_P(HostapdAidl, AddInvalidPskAccessPointWithoutAcs) {
429     std::string ifname = setupApIfaceAndGetName(false);
430     auto status =
431             hostapd->addAccessPoint(getIfaceParamsWithoutAcs(ifname), getInvalidPskNwParams());
432     EXPECT_FALSE(status.isOk());
433 }
434 
435 /**
436  * Adds an access point with invalid SAE transition network config.
437  * Access point creation should fail.
438  */
TEST_P(HostapdAidl,AddInvalidSaeTransitionAccessPointWithoutAcs)439 TEST_P(HostapdAidl, AddInvalidSaeTransitionAccessPointWithoutAcs) {
440     std::string ifname = setupApIfaceAndGetName(false);
441     if (!isWpa3SaeSupport) GTEST_SKIP() << "Missing SAE support";
442     auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(ifname),
443                                           getInvalidSaeTransitionNwParams());
444     EXPECT_FALSE(status.isOk());
445 }
446 
447 /**
448  * Adds an access point with invalid SAE network config.
449  * Access point creation should fail.
450  */
TEST_P(HostapdAidl,AddInvalidSaeAccessPointWithoutAcs)451 TEST_P(HostapdAidl, AddInvalidSaeAccessPointWithoutAcs) {
452     std::string ifname = setupApIfaceAndGetName(false);
453     if (!isWpa3SaeSupport) GTEST_SKIP() << "Missing SAE support";
454     auto status =
455             hostapd->addAccessPoint(getIfaceParamsWithoutAcs(ifname), getInvalidSaeNwParams());
456     EXPECT_FALSE(status.isOk());
457 }
458 
459 /**
460  * forceClientDisconnect should fail when hotspot interface available.
461  */
TEST_P(HostapdAidl,DisconnectClientWhenIfacAvailable)462 TEST_P(HostapdAidl, DisconnectClientWhenIfacAvailable) {
463     std::string ifname = setupApIfaceAndGetName(false);
464     auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(ifname), getOpenNwParams());
465     EXPECT_TRUE(status.isOk());
466 
467     status = hostapd->forceClientDisconnect(ifname, kTestZeroMacAddr, kTestDisconnectReasonCode);
468     EXPECT_FALSE(status.isOk());
469 }
470 
471 /**
472  * AddAccessPointWithDualBandConfig should pass
473  */
TEST_P(HostapdAidl,AddAccessPointWithDualBandConfig)474 TEST_P(HostapdAidl, AddAccessPointWithDualBandConfig) {
475     if (!isBridgedSupport) GTEST_SKIP() << "Missing Bridged AP support";
476     std::string ifname = setupApIfaceAndGetName(true);
477     auto status =
478             hostapd->addAccessPoint(getIfaceParamsWithBridgedModeACS(ifname), getOpenNwParams());
479     EXPECT_TRUE(status.isOk());
480 }
481 
482 /**
483  * AddAccessPointWithMloConfig and remove link should pass
484  */
TEST_P(HostapdAidl,AddAccessPointWithMloConfigAndRemoveInstance)485 TEST_P(HostapdAidl, AddAccessPointWithMloConfigAndRemoveInstance) {
486     if (interface_version_ < 3) {
487         GTEST_SKIP() << "MLO SAP is available in IfaceParams as of Hostapd V3";
488     }
489     if (!isMloSupport) GTEST_SKIP() << "Missing MLO AP support";
490     std::shared_ptr<IWifiApIface> wifi_ap_iface = HostapdAidlTestUtils::setupMloApIface();
491     EXPECT_TRUE(wifi_ap_iface.get() != nullptr);
492     std::string br_name;
493     std::vector<std::string> instances;
494     bool uses_mlo;
495     EXPECT_TRUE(wifi_ap_iface->getName(&br_name).isOk());
496     EXPECT_TRUE(wifi_ap_iface->getBridgedInstances(&instances).isOk());
497     EXPECT_TRUE(wifi_ap_iface->usesMlo(&uses_mlo).isOk());
498     EXPECT_TRUE(uses_mlo);
499 
500     IfaceParams iface_params = getIfaceParamsWithBridgedModeACS(br_name);
501     iface_params.instanceIdentities = {instances[0], instances[1]};
502     iface_params.usesMlo = uses_mlo;
503     iface_params.hwModeParams.enable80211AX = true;
504     iface_params.hwModeParams.enable80211BE = true;
505 
506     EXPECT_TRUE(hostapd->addAccessPoint(iface_params, getSaeNwParams()).isOk());
507     EXPECT_TRUE(hostapd->removeLinkFromMultipleLinkBridgedApIface(br_name, instances[0]).isOk());
508 }
509 
510 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HostapdAidl);
511 INSTANTIATE_TEST_SUITE_P(
512     Hostapd, HostapdAidl,
513     testing::ValuesIn(android::getAidlHalInstanceNames(IHostapd::descriptor)),
514     android::PrintInstanceNameToString);
515 
main(int argc,char ** argv)516 int main(int argc, char **argv) {
517     ::testing::InitGoogleTest(&argc, argv);
518     ProcessState::self()->setThreadPoolMaxThreadCount(1);
519     ProcessState::self()->startThreadPool();
520     return RUN_ALL_TESTS();
521 }
522