1 /*
2 * Copyright (C) 2016 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
17 #include <android-base/logging.h>
18 #include <cutils/properties.h>
19
20 #include <android/hidl/manager/1.0/IServiceManager.h>
21 #include <android/hidl/manager/1.0/IServiceNotification.h>
22 #include <hidl/HidlTransportSupport.h>
23
24 #include <wifi_system/interface_tool.h>
25 #include <wifi_system/supplicant_manager.h>
26
27 #include "supplicant_hidl_test_utils.h"
28 #include "wifi_hidl_test_utils.h"
29
30 using ::android::sp;
31 using ::android::hardware::configureRpcThreadpool;
32 using ::android::hardware::joinRpcThreadpool;
33 using ::android::hardware::hidl_string;
34 using ::android::hardware::hidl_vec;
35 using ::android::hardware::Return;
36 using ::android::hardware::Void;
37 using ::android::hardware::wifi::V1_0::ChipModeId;
38 using ::android::hardware::wifi::V1_0::IWifiChip;
39 using ::android::hardware::wifi::supplicant::V1_0::ISupplicant;
40 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantIface;
41 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantNetwork;
42 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantStaIface;
43 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantStaNetwork;
44 using ::android::hardware::wifi::supplicant::V1_0::ISupplicantP2pIface;
45 using ::android::hardware::wifi::supplicant::V1_0::IfaceType;
46 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
47 using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
48 using ::android::hidl::manager::V1_0::IServiceNotification;
49 using ::android::wifi_system::InterfaceTool;
50 using ::android::wifi_system::SupplicantManager;
51
52 namespace {
53
54 // Helper function to initialize the driver and firmware to STA mode
55 // using the vendor HAL HIDL interface.
initilializeDriverAndFirmware(const std::string & wifi_instance_name)56 void initilializeDriverAndFirmware(const std::string& wifi_instance_name) {
57 // Skip if wifi instance is not set.
58 if (wifi_instance_name == "") {
59 return;
60 }
61
62 sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
63 ChipModeId mode_id;
64 EXPECT_TRUE(configureChipToSupportIfaceType(
65 wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::STA, &mode_id));
66 }
67
68 // Helper function to deinitialize the driver and firmware
69 // using the vendor HAL HIDL interface.
deInitilializeDriverAndFirmware(const std::string & wifi_instance_name)70 void deInitilializeDriverAndFirmware(const std::string& wifi_instance_name) {
71 // Skip if wifi instance is not set.
72 if (wifi_instance_name == "") {
73 return;
74 }
75
76 stopWifi(wifi_instance_name);
77 }
78
79 // Helper function to find any iface of the desired type exposed.
findIfaceOfType(sp<ISupplicant> supplicant,IfaceType desired_type,ISupplicant::IfaceInfo * out_info)80 bool findIfaceOfType(sp<ISupplicant> supplicant, IfaceType desired_type,
81 ISupplicant::IfaceInfo* out_info) {
82 bool operation_failed = false;
83 std::vector<ISupplicant::IfaceInfo> iface_infos;
84 supplicant->listInterfaces([&](const SupplicantStatus& status,
85 hidl_vec<ISupplicant::IfaceInfo> infos) {
86 if (status.code != SupplicantStatusCode::SUCCESS) {
87 operation_failed = true;
88 return;
89 }
90 iface_infos = infos;
91 });
92 if (operation_failed) {
93 return false;
94 }
95 for (const auto& info : iface_infos) {
96 if (info.type == desired_type) {
97 *out_info = info;
98 return true;
99 }
100 }
101 return false;
102 }
103
getStaIfaceName()104 std::string getStaIfaceName() {
105 std::array<char, PROPERTY_VALUE_MAX> buffer;
106 property_get("wifi.interface", buffer.data(), "wlan0");
107 return buffer.data();
108 }
109
getP2pIfaceName()110 std::string getP2pIfaceName() {
111 std::array<char, PROPERTY_VALUE_MAX> buffer;
112 property_get("wifi.direct.interface", buffer.data(), "p2p0");
113 return buffer.data();
114 }
115 } // namespace
116
117 // Utility class to wait for wpa_supplicant's HIDL service registration.
118 class ServiceNotificationListener : public IServiceNotification {
119 public:
onRegistration(const hidl_string & fully_qualified_name,const hidl_string & instance_name,bool pre_existing)120 Return<void> onRegistration(const hidl_string& fully_qualified_name,
121 const hidl_string& instance_name,
122 bool pre_existing) override {
123 if (pre_existing) {
124 return Void();
125 }
126 std::unique_lock<std::mutex> lock(mutex_);
127 registered_.push_back(std::string(fully_qualified_name.c_str()) + "/" +
128 instance_name.c_str());
129 lock.unlock();
130 condition_.notify_one();
131 return Void();
132 }
133
registerForHidlServiceNotifications(const std::string & instance_name)134 bool registerForHidlServiceNotifications(const std::string& instance_name) {
135 if (!ISupplicant::registerForNotifications(instance_name, this)) {
136 return false;
137 }
138 configureRpcThreadpool(2, false);
139 return true;
140 }
141
waitForHidlService(uint32_t timeout_in_millis,const std::string & instance_name)142 bool waitForHidlService(uint32_t timeout_in_millis,
143 const std::string& instance_name) {
144 std::unique_lock<std::mutex> lock(mutex_);
145 condition_.wait_for(lock, std::chrono::milliseconds(timeout_in_millis),
146 [&]() { return registered_.size() >= 1; });
147 if (registered_.size() != 1) {
148 return false;
149 }
150 std::string exptected_registered =
151 std::string(ISupplicant::descriptor) + "/" + instance_name;
152 if (registered_[0] != exptected_registered) {
153 LOG(ERROR) << "Expected: " << exptected_registered
154 << ", Got: " << registered_[0];
155 return false;
156 }
157 return true;
158 }
159
160 private:
161 std::vector<std::string> registered_{};
162 std::mutex mutex_;
163 std::condition_variable condition_;
164 };
165
stopSupplicant()166 void stopSupplicant() { stopSupplicant(""); }
167
stopSupplicant(const std::string & wifi_instance_name)168 void stopSupplicant(const std::string& wifi_instance_name) {
169 SupplicantManager supplicant_manager;
170
171 ASSERT_TRUE(supplicant_manager.StopSupplicant());
172 deInitilializeDriverAndFirmware(wifi_instance_name);
173 ASSERT_FALSE(supplicant_manager.IsSupplicantRunning());
174 }
175
startSupplicantAndWaitForHidlService(const std::string & wifi_instance_name,const std::string & supplicant_instance_name)176 void startSupplicantAndWaitForHidlService(
177 const std::string& wifi_instance_name,
178 const std::string& supplicant_instance_name) {
179 initilializeDriverAndFirmware(wifi_instance_name);
180
181 android::sp<ServiceNotificationListener> notification_listener =
182 new ServiceNotificationListener();
183 ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications(
184 supplicant_instance_name));
185
186 SupplicantManager supplicant_manager;
187 ASSERT_TRUE(supplicant_manager.StartSupplicant());
188 ASSERT_TRUE(supplicant_manager.IsSupplicantRunning());
189
190 ASSERT_TRUE(notification_listener->waitForHidlService(
191 500, supplicant_instance_name));
192 }
193
is_1_1(const sp<ISupplicant> & supplicant)194 bool is_1_1(const sp<ISupplicant>& supplicant) {
195 sp<::android::hardware::wifi::supplicant::V1_1::ISupplicant>
196 supplicant_1_1 =
197 ::android::hardware::wifi::supplicant::V1_1::ISupplicant::castFrom(
198 supplicant);
199 return supplicant_1_1.get() != nullptr;
200 }
201
addSupplicantStaIface_1_1(const sp<ISupplicant> & supplicant)202 void addSupplicantStaIface_1_1(const sp<ISupplicant>& supplicant) {
203 sp<::android::hardware::wifi::supplicant::V1_1::ISupplicant>
204 supplicant_1_1 =
205 ::android::hardware::wifi::supplicant::V1_1::ISupplicant::castFrom(
206 supplicant);
207 ASSERT_TRUE(supplicant_1_1.get());
208 ISupplicant::IfaceInfo info = {IfaceType::STA, getStaIfaceName()};
209 supplicant_1_1->addInterface(
210 info, [&](const SupplicantStatus& status,
211 const sp<ISupplicantIface>& /* iface */) {
212 ASSERT_TRUE(
213 (SupplicantStatusCode::SUCCESS == status.code) ||
214 (SupplicantStatusCode::FAILURE_IFACE_EXISTS == status.code));
215 });
216 }
217
addSupplicantP2pIface_1_1(const sp<ISupplicant> & supplicant)218 void addSupplicantP2pIface_1_1(const sp<ISupplicant>& supplicant) {
219 sp<::android::hardware::wifi::supplicant::V1_1::ISupplicant>
220 supplicant_1_1 =
221 ::android::hardware::wifi::supplicant::V1_1::ISupplicant::castFrom(
222 supplicant);
223 ASSERT_TRUE(supplicant_1_1.get());
224 ISupplicant::IfaceInfo info = {IfaceType::P2P, getP2pIfaceName()};
225 supplicant_1_1->addInterface(
226 info, [&](const SupplicantStatus& status,
227 const sp<ISupplicantIface>& /* iface */) {
228 ASSERT_TRUE(
229 (SupplicantStatusCode::SUCCESS == status.code) ||
230 (SupplicantStatusCode::FAILURE_IFACE_EXISTS == status.code));
231 });
232 }
233
getSupplicant(const std::string & supplicant_instance_name,bool isP2pOn)234 sp<ISupplicant> getSupplicant(const std::string& supplicant_instance_name,
235 bool isP2pOn) {
236 sp<ISupplicant> supplicant =
237 ISupplicant::getService(supplicant_instance_name);
238 // For 1.1 supplicant, we need to add interfaces at initialization.
239 if (is_1_1(supplicant)) {
240 addSupplicantStaIface_1_1(supplicant);
241 if (isP2pOn) {
242 addSupplicantP2pIface_1_1(supplicant);
243 }
244 }
245 return supplicant;
246 }
247
getSupplicantStaIface(const sp<ISupplicant> & supplicant)248 sp<ISupplicantStaIface> getSupplicantStaIface(
249 const sp<ISupplicant>& supplicant) {
250 if (!supplicant.get()) {
251 return nullptr;
252 }
253 ISupplicant::IfaceInfo info;
254 if (!findIfaceOfType(supplicant, IfaceType::STA, &info)) {
255 return nullptr;
256 }
257 bool operation_failed = false;
258 sp<ISupplicantStaIface> sta_iface;
259 supplicant->getInterface(info, [&](const SupplicantStatus& status,
260 const sp<ISupplicantIface>& iface) {
261 if (status.code != SupplicantStatusCode::SUCCESS) {
262 operation_failed = true;
263 return;
264 }
265 sta_iface = ISupplicantStaIface::castFrom(iface);
266 });
267 if (operation_failed) {
268 return nullptr;
269 }
270 return sta_iface;
271 }
272
createSupplicantStaNetwork(const sp<ISupplicant> & supplicant)273 sp<ISupplicantStaNetwork> createSupplicantStaNetwork(
274 const sp<ISupplicant>& supplicant) {
275 sp<ISupplicantStaIface> sta_iface = getSupplicantStaIface(supplicant);
276 if (!sta_iface.get()) {
277 return nullptr;
278 }
279 bool operation_failed = false;
280 sp<ISupplicantStaNetwork> sta_network;
281 sta_iface->addNetwork([&](const SupplicantStatus& status,
282 const sp<ISupplicantNetwork>& network) {
283 if (status.code != SupplicantStatusCode::SUCCESS) {
284 operation_failed = true;
285 return;
286 }
287 sta_network = ISupplicantStaNetwork::castFrom(network);
288 });
289 if (operation_failed) {
290 return nullptr;
291 }
292 return sta_network;
293 }
294
getSupplicantP2pIface(const sp<ISupplicant> & supplicant)295 sp<ISupplicantP2pIface> getSupplicantP2pIface(
296 const sp<ISupplicant>& supplicant) {
297 if (!supplicant.get()) {
298 return nullptr;
299 }
300 ISupplicant::IfaceInfo info;
301 if (!findIfaceOfType(supplicant, IfaceType::P2P, &info)) {
302 return nullptr;
303 }
304 bool operation_failed = false;
305 sp<ISupplicantP2pIface> p2p_iface;
306 supplicant->getInterface(info, [&](const SupplicantStatus& status,
307 const sp<ISupplicantIface>& iface) {
308 if (status.code != SupplicantStatusCode::SUCCESS) {
309 operation_failed = true;
310 return;
311 }
312 p2p_iface = ISupplicantP2pIface::castFrom(iface);
313 });
314 if (operation_failed) {
315 return nullptr;
316 }
317 return p2p_iface;
318 }
319
turnOnExcessiveLogging(const sp<ISupplicant> & supplicant)320 bool turnOnExcessiveLogging(const sp<ISupplicant>& supplicant) {
321 if (!supplicant.get()) {
322 return false;
323 }
324 bool operation_failed = false;
325 supplicant->setDebugParams(
326 ISupplicant::DebugLevel::EXCESSIVE,
327 true, // show timestamps
328 true, // show keys
329 [&](const SupplicantStatus& status) {
330 if (status.code != SupplicantStatusCode::SUCCESS) {
331 operation_failed = true;
332 }
333 });
334 return !operation_failed;
335 }
336