• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * WPA Supplicant - Supplicant Aidl interface
3  * Copyright (c) 2021, Google Inc. All rights reserved.
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "aidl_manager.h"
10 #include "aidl_return_util.h"
11 #include "misc_utils.h"
12 #include "supplicant.h"
13 #include "p2p_iface.h"
14 
15 #include <android-base/file.h>
16 #include <fcntl.h>
17 #include <sys/stat.h>
18 
19 namespace {
20 
21 // Pre-populated interface params for interfaces controlled by wpa_supplicant.
22 // Note: This may differ for other OEM's. So, modify this accordingly.
23 constexpr char kIfaceDriverName[] = "nl80211";
24 constexpr char kStaIfaceConfPath[] =
25 	"/data/vendor/wifi/wpa/wpa_supplicant.conf";
26 static const char* kStaIfaceConfOverlayPaths[] = {
27     "/apex/com.android.wifi.hal/etc/wifi/wpa_supplicant_overlay.conf",
28     "/vendor/etc/wifi/wpa_supplicant_overlay.conf",
29 };
30 constexpr char kP2pIfaceConfPath[] =
31 	"/data/vendor/wifi/wpa/p2p_supplicant.conf";
32 static const char* kP2pIfaceConfOverlayPaths[] = {
33     "/apex/com.android.wifi.hal/etc/wifi/p2p_supplicant_overlay.conf",
34     "/vendor/etc/wifi/p2p_supplicant_overlay.conf",
35 };
36 // Migrate conf files for existing devices.
37 static const char* kTemplateConfPaths[] = {
38     "/apex/com.android.wifi.hal/etc/wifi/wpa_supplicant.conf",
39     "/vendor/etc/wifi/wpa_supplicant.conf",
40     "/system/etc/wifi/wpa_supplicant.conf",
41 };
42 constexpr char kOldStaIfaceConfPath[] = "/data/misc/wifi/wpa_supplicant.conf";
43 constexpr char kOldP2pIfaceConfPath[] = "/data/misc/wifi/p2p_supplicant.conf";
44 constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
45 
resolvePath(const char * paths[],size_t size)46 const char* resolvePath(const char* paths[], size_t size)
47 {
48 	for (int i = 0; i < size; ++i) {
49 		if (access(paths[i], R_OK) == 0) {
50 			return paths[i];
51 		}
52 	}
53 	return nullptr;
54 }
55 
copyFile(const std::string & src_file_path,const std::string & dest_file_path)56 int copyFile(
57 	const std::string& src_file_path, const std::string& dest_file_path)
58 {
59 	std::string file_contents;
60 	if (!android::base::ReadFileToString(src_file_path, &file_contents)) {
61 		wpa_printf(
62 			MSG_ERROR, "Failed to read from %s. Errno: %s",
63 			src_file_path.c_str(), strerror(errno));
64 		return -1;
65 	}
66 	if (!android::base::WriteStringToFile(
67 		file_contents, dest_file_path, kConfigFileMode, getuid(),
68 		getgid())) {
69 		wpa_printf(
70 			MSG_ERROR, "Failed to write to %s. Errno: %s",
71 			dest_file_path.c_str(), strerror(errno));
72 		return -1;
73 	}
74 	return 0;
75 }
76 
77 /**
78  * Copy |src_file_path| to |dest_file_path| if it exists.
79  *
80  * Returns 1 if |src_file_path| does not exist or not accessible,
81  * Returns -1 if the copy fails.
82  * Returns 0 if the copy succeeds.
83  */
copyFileIfItExists(const std::string & src_file_path,const std::string & dest_file_path)84 int copyFileIfItExists(
85 	const std::string& src_file_path, const std::string& dest_file_path)
86 {
87 	int ret = access(src_file_path.c_str(), R_OK);
88 	// Sepolicy denial (2018+ device) will return EACCESS instead of ENOENT.
89 	if ((ret != 0) && ((errno == ENOENT) || (errno == EACCES))) {
90 		return 1;
91 	}
92 	ret = copyFile(src_file_path, dest_file_path);
93 	if (ret != 0) {
94 		wpa_printf(
95 			MSG_ERROR, "Failed copying %s to %s.",
96 			src_file_path.c_str(), dest_file_path.c_str());
97 		return -1;
98 	}
99 	return 0;
100 }
101 
102 /**
103  * Ensure that the specified config file pointed by |config_file_path| exists.
104  * a) If the |config_file_path| exists with the correct permissions, return.
105  * b) If the |config_file_path| does not exist, but |old_config_file_path|
106  * exists, copy over the contents of the |old_config_file_path| to
107  * |config_file_path|.
108  * c) If the |config_file_path| & |old_config_file_path|
109  * does not exists, copy over the contents of |template_config_file_path|.
110  */
ensureConfigFileExists(const std::string & config_file_path,const std::string & old_config_file_path)111 int ensureConfigFileExists(
112 	const std::string& config_file_path,
113 	const std::string& old_config_file_path)
114 {
115 	int ret = access(config_file_path.c_str(), R_OK | W_OK);
116 	if (ret == 0) {
117 		return 0;
118 	}
119 	if (errno == EACCES) {
120 		ret = chmod(config_file_path.c_str(), kConfigFileMode);
121 		if (ret == 0) {
122 			return 0;
123 		} else {
124 			wpa_printf(
125 				MSG_ERROR, "Cannot set RW to %s. Errno: %s",
126 				config_file_path.c_str(), strerror(errno));
127 			return -1;
128 		}
129 	} else if (errno != ENOENT) {
130 		wpa_printf(
131 			MSG_ERROR, "Cannot acces %s. Errno: %s",
132 			config_file_path.c_str(), strerror(errno));
133 		return -1;
134 	}
135 	ret = copyFileIfItExists(old_config_file_path, config_file_path);
136 	if (ret == 0) {
137 		wpa_printf(
138 			MSG_INFO, "Migrated conf file from %s to %s",
139 			old_config_file_path.c_str(), config_file_path.c_str());
140 		unlink(old_config_file_path.c_str());
141 		return 0;
142 	} else if (ret == -1) {
143 		unlink(config_file_path.c_str());
144 		return -1;
145 	}
146 	const char* path =
147 	    resolvePath(kTemplateConfPaths,
148 	    sizeof(kTemplateConfPaths)/sizeof(kTemplateConfPaths[0]));
149 	if (path != nullptr) {
150 		ret = copyFileIfItExists(path, config_file_path);
151 		if (ret == 0) {
152 			wpa_printf(
153 			    MSG_INFO, "Copied template conf file from %s to %s",
154 			    path, config_file_path.c_str());
155 			return 0;
156 		} else if (ret == -1) {
157 			unlink(config_file_path.c_str());
158 			return -1;
159 		}
160 	}
161 	// Did not create the conf file.
162 	return -1;
163 }
164 }  // namespace
165 
166 namespace aidl {
167 namespace android {
168 namespace hardware {
169 namespace wifi {
170 namespace supplicant {
171 using aidl_return_util::validateAndCall;
172 using misc_utils::createStatus;
173 using misc_utils::createStatusWithMsg;
174 
Supplicant(struct wpa_global * global)175 Supplicant::Supplicant(struct wpa_global* global) : wpa_global_(global) {}
isValid()176 bool Supplicant::isValid()
177 {
178 	// This top level object cannot be invalidated.
179 	return true;
180 }
181 
addP2pInterface(const std::string & in_name,std::shared_ptr<ISupplicantP2pIface> * _aidl_return)182 ::ndk::ScopedAStatus Supplicant::addP2pInterface(
183 	const std::string& in_name,
184 	std::shared_ptr<ISupplicantP2pIface>* _aidl_return)
185 {
186 	return validateAndCall(
187 		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
188 		&Supplicant::addP2pInterfaceInternal, _aidl_return, in_name);
189 }
190 
addStaInterface(const std::string & in_name,std::shared_ptr<ISupplicantStaIface> * _aidl_return)191 ::ndk::ScopedAStatus Supplicant::addStaInterface(
192 	const std::string& in_name,
193 	std::shared_ptr<ISupplicantStaIface>* _aidl_return)
194 {
195 	return validateAndCall(
196 		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
197 		&Supplicant::addStaInterfaceInternal, _aidl_return, in_name);
198 }
199 
removeInterface(const IfaceInfo & in_ifaceInfo)200 ::ndk::ScopedAStatus Supplicant::removeInterface(
201 	const IfaceInfo& in_ifaceInfo)
202 {
203 	return validateAndCall(
204 		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
205 		&Supplicant::removeInterfaceInternal, in_ifaceInfo);
206 }
207 
getP2pInterface(const std::string & in_name,std::shared_ptr<ISupplicantP2pIface> * _aidl_return)208 ::ndk::ScopedAStatus Supplicant::getP2pInterface(
209 	const std::string& in_name,
210 	std::shared_ptr<ISupplicantP2pIface>* _aidl_return)
211 {
212 	return validateAndCall(
213 		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
214 		&Supplicant::getP2pInterfaceInternal, _aidl_return, in_name);
215 }
216 
getStaInterface(const std::string & in_name,std::shared_ptr<ISupplicantStaIface> * _aidl_return)217 ::ndk::ScopedAStatus Supplicant::getStaInterface(
218 	const std::string& in_name,
219 	std::shared_ptr<ISupplicantStaIface>* _aidl_return)
220 {
221 	return validateAndCall(
222 		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
223 		&Supplicant::getStaInterfaceInternal, _aidl_return, in_name);
224 }
225 
listInterfaces(std::vector<IfaceInfo> * _aidl_return)226 ::ndk::ScopedAStatus Supplicant::listInterfaces(
227 	std::vector<IfaceInfo>* _aidl_return)
228 {
229 	return validateAndCall(
230 		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
231 		&Supplicant::listInterfacesInternal, _aidl_return);
232 }
233 
registerCallback(const std::shared_ptr<ISupplicantCallback> & in_callback)234 ::ndk::ScopedAStatus Supplicant::registerCallback(
235 	const std::shared_ptr<ISupplicantCallback>& in_callback)
236 {
237 	return validateAndCall(
238 		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
239 		&Supplicant::registerCallbackInternal, in_callback);
240 }
241 
setDebugParams(DebugLevel in_level,bool in_showTimestamp,bool in_showKeys)242 ::ndk::ScopedAStatus Supplicant::setDebugParams(
243 	DebugLevel in_level, bool in_showTimestamp,
244 	bool in_showKeys)
245 {
246 	return validateAndCall(
247 		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
248 		&Supplicant::setDebugParamsInternal, in_level,
249 		in_showTimestamp, in_showKeys);
250 }
251 
setConcurrencyPriority(IfaceType in_type)252 ::ndk::ScopedAStatus Supplicant::setConcurrencyPriority(
253 	IfaceType in_type)
254 {
255 	return validateAndCall(
256 		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
257 		&Supplicant::setConcurrencyPriorityInternal, in_type);
258 }
259 
getDebugLevel(DebugLevel * _aidl_return)260 ::ndk::ScopedAStatus Supplicant::getDebugLevel(DebugLevel* _aidl_return)
261 {
262 	*_aidl_return = static_cast<DebugLevel>(wpa_debug_level);
263 	return ndk::ScopedAStatus::ok();
264 }
265 
isDebugShowTimestampEnabled(bool * _aidl_return)266 ::ndk::ScopedAStatus Supplicant::isDebugShowTimestampEnabled(bool* _aidl_return)
267 {
268 	*_aidl_return = ((wpa_debug_timestamp != 0) ? true : false);
269 	return ndk::ScopedAStatus::ok();
270 }
271 
isDebugShowKeysEnabled(bool * _aidl_return)272 ::ndk::ScopedAStatus Supplicant::isDebugShowKeysEnabled(bool* _aidl_return)
273 {
274 	*_aidl_return = ((wpa_debug_show_keys != 0) ? true : false);
275 	return ndk::ScopedAStatus::ok();
276 }
277 
terminate()278 ::ndk::ScopedAStatus Supplicant::terminate()
279 {
280 	wpa_printf(MSG_INFO, "Terminating...");
281 	wpa_supplicant_terminate_proc(wpa_global_);
282 	return ndk::ScopedAStatus::ok();
283 }
284 
addP2pDevInterface(struct wpa_interface iface_params)285 ndk::ScopedAStatus Supplicant::addP2pDevInterface(struct wpa_interface iface_params)
286 {
287 	char primary_ifname[IFNAMSIZ];
288 	u32 primary_ifname_len =
289 		strlen(iface_params.ifname) - strlen(P2P_MGMT_DEVICE_PREFIX);
290 
291 	if(primary_ifname_len > IFNAMSIZ) {
292 		wpa_printf(MSG_DEBUG, "%s, Invalid primary iface name ", __FUNCTION__);
293 		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
294 	}
295 
296 	strncpy(primary_ifname, iface_params.ifname +
297 		strlen(P2P_MGMT_DEVICE_PREFIX), primary_ifname_len);
298 	wpa_printf(MSG_DEBUG, "%s, Initialize p2p-dev-wlan0 iface with"
299 		"primary_iface = %s", __FUNCTION__, primary_ifname);
300 	struct wpa_supplicant* wpa_s =
301 		wpa_supplicant_get_iface(wpa_global_, primary_ifname);
302 	if (!wpa_s) {
303 		wpa_printf(MSG_DEBUG, "%s,NULL wpa_s for wlan0", __FUNCTION__);
304 		return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
305 	}
306 
307 	const u8 *if_addr = NULL;
308 	char force_name[100] = {'\0'};
309 	wpa_s->pending_interface_type = WPA_IF_P2P_DEVICE;
310 	if (wpa_s->conf->p2p_device_random_mac_addr == 2 &&
311 		!is_zero_ether_addr(wpa_s->conf->p2p_device_persistent_mac_addr))
312 		if_addr = wpa_s->conf->p2p_device_persistent_mac_addr;
313 
314 	int ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, iface_params.ifname, if_addr, NULL,
315 		force_name, wpa_s->pending_interface_addr, NULL);
316 	if (ret < 0) {
317 		wpa_printf(MSG_DEBUG, "P2P: Failed to create P2P Device interface");
318 		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
319 	}
320 
321 	os_strlcpy(wpa_s->pending_interface_name, iface_params.ifname,
322 		sizeof(wpa_s->pending_interface_name));
323 	iface_params.p2p_mgmt = 1;
324 	iface_params.driver_param = wpa_s->conf->driver_param;
325 	iface_params.ctrl_interface = NULL;
326 
327 	struct wpa_supplicant *p2pdev_wpa_s = wpa_supplicant_add_iface(
328 		wpa_s->global, &iface_params, wpa_s);
329 
330 	if (!p2pdev_wpa_s) {
331 		wpa_printf(MSG_INFO,
332 			"Failed to enable P2P Device");
333 		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
334 	}
335 	p2pdev_wpa_s->p2pdev = p2pdev_wpa_s;
336 	wpa_s->pending_interface_name[0] = '\0';
337 
338 	return ndk::ScopedAStatus::ok();
339 }
340 
341 std::pair<std::shared_ptr<ISupplicantP2pIface>, ndk::ScopedAStatus>
addP2pInterfaceInternal(const std::string & name)342 Supplicant::addP2pInterfaceInternal(const std::string& name)
343 {
344 	std::shared_ptr<ISupplicantP2pIface> iface;
345 
346 	// Check if required |ifname| argument is empty.
347 	if (name.empty()) {
348 		return {nullptr, createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID)};
349 	}
350 	if (strncmp(name.c_str(), P2P_MGMT_DEVICE_PREFIX, strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
351 		struct wpa_supplicant* wpa_s = wpa_supplicant_get_iface(wpa_global_, name.c_str());
352 		if (wpa_s) {
353 			wpa_printf(MSG_DEBUG, "Remove existing p2p dev interface");
354 			wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0);
355 		}
356 	}
357 	// Try to get the wpa_supplicant record for this iface, return
358 	// the iface object with the appropriate status code if it exists.
359 	ndk::ScopedAStatus status;
360 	std::tie(iface, status) = getP2pInterfaceInternal(name);
361 	if (status.isOk()) {
362 		wpa_printf(MSG_INFO, "Iface already exists, return existing");
363 		return {iface, ndk::ScopedAStatus::ok()};
364 	}
365 
366 	struct wpa_interface iface_params = {};
367 	iface_params.driver = kIfaceDriverName;
368 	if (ensureConfigFileExists(
369 		kP2pIfaceConfPath, kOldP2pIfaceConfPath) != 0) {
370 		wpa_printf(
371 			MSG_ERROR, "Conf file does not exists: %s",
372 			kP2pIfaceConfPath);
373 		return {nullptr, createStatusWithMsg(
374 			SupplicantStatusCode::FAILURE_UNKNOWN, "Conf file does not exist")};
375 	}
376 	iface_params.confname = kP2pIfaceConfPath;
377 	const char* path = resolvePath(
378 		    kP2pIfaceConfOverlayPaths,
379 		    sizeof(kP2pIfaceConfOverlayPaths)/sizeof(kP2pIfaceConfOverlayPaths[0]));
380 	if (path != nullptr) {
381 		iface_params.confanother = path;
382 	}
383 
384 	iface_params.ifname = name.c_str();
385 	if (strncmp(iface_params.ifname, P2P_MGMT_DEVICE_PREFIX,
386 		strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
387 		status = addP2pDevInterface(iface_params);
388 		if (!status.isOk()) {
389 			return {iface, createStatus(static_cast<SupplicantStatusCode>(
390 				status.getServiceSpecificError()))};
391 		}
392 	} else {
393 		struct wpa_supplicant* wpa_s =
394 			wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
395 		if (!wpa_s) {
396 			return {nullptr, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
397 		}
398 		// Request the current scan results from the driver and update
399 		// the local BSS list wpa_s->bss. This is to avoid a full scan
400 		// while processing the connect request on newly created interface.
401 		wpa_supplicant_update_scan_results(wpa_s);
402 	}
403 	// The supplicant core creates a corresponding aidl object via
404 	// AidlManager when |wpa_supplicant_add_iface| is called.
405 	return getP2pInterfaceInternal(name);
406 }
407 
408 std::pair<std::shared_ptr<ISupplicantStaIface>, ndk::ScopedAStatus>
addStaInterfaceInternal(const std::string & name)409 Supplicant::addStaInterfaceInternal(const std::string& name)
410 {
411 	std::shared_ptr<ISupplicantStaIface> iface;
412 
413 	// Check if required |ifname| argument is empty.
414 	if (name.empty()) {
415 		return {nullptr, createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID)};
416 	}
417 	// Try to get the wpa_supplicant record for this iface, return
418 	// the iface object with the appropriate status code if it exists.
419 	ndk::ScopedAStatus status;
420 	std::tie(iface, status) = getStaInterfaceInternal(name);
421 	if (status.isOk()) {
422 		wpa_printf(MSG_INFO, "Iface already exists, return existing");
423 		return {iface, ndk::ScopedAStatus::ok()};
424 	}
425 
426 	struct wpa_interface iface_params = {};
427 	iface_params.driver = kIfaceDriverName;
428 	if (ensureConfigFileExists(
429 		kStaIfaceConfPath, kOldStaIfaceConfPath) != 0) {
430 		wpa_printf(
431 			MSG_ERROR, "Conf file does not exists: %s",
432 			kStaIfaceConfPath);
433 		return {nullptr, createStatusWithMsg(
434 			SupplicantStatusCode::FAILURE_UNKNOWN, "Conf file does not exist")};
435 	}
436 	iface_params.confname = kStaIfaceConfPath;
437 	const char* path = resolvePath(
438 		    kStaIfaceConfOverlayPaths,
439 		    sizeof(kStaIfaceConfOverlayPaths)/sizeof(kStaIfaceConfOverlayPaths[0]));
440 	if (path != nullptr) {
441 		iface_params.confanother = path;
442 	}
443 
444 	iface_params.ifname = name.c_str();
445 	if (strncmp(iface_params.ifname, P2P_MGMT_DEVICE_PREFIX,
446 		strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
447 		status = addP2pDevInterface(iface_params);
448 		if (!status.isOk()) {
449 			return {iface, createStatus(static_cast<SupplicantStatusCode>(
450 				status.getServiceSpecificError()))};
451 		}
452 	} else {
453 		struct wpa_supplicant* wpa_s =
454 			wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
455 		if (!wpa_s) {
456 			return {nullptr, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
457 		}
458 		// Request the current scan results from the driver and update
459 		// the local BSS list wpa_s->bss. This is to avoid a full scan
460 		// while processing the connect request on newly created interface.
461 		wpa_supplicant_update_scan_results(wpa_s);
462 	}
463 	// The supplicant core creates a corresponding aidl object via
464 	// AidlManager when |wpa_supplicant_add_iface| is called.
465 	return getStaInterfaceInternal(name);
466 }
467 
removeInterfaceInternal(const IfaceInfo & iface_info)468 ndk::ScopedAStatus Supplicant::removeInterfaceInternal(
469 	const IfaceInfo& iface_info)
470 {
471 	struct wpa_supplicant* wpa_s =
472 		wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
473 	if (!wpa_s) {
474 		return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
475 	}
476 	if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
477 		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
478 	}
479 	return ndk::ScopedAStatus::ok();
480 }
481 
482 std::pair<std::shared_ptr<ISupplicantP2pIface>, ndk::ScopedAStatus>
getP2pInterfaceInternal(const std::string & name)483 Supplicant::getP2pInterfaceInternal(const std::string& name)
484 {
485 	struct wpa_supplicant* wpa_s =
486 		wpa_supplicant_get_iface(wpa_global_, name.c_str());
487 	if (!wpa_s) {
488 		return {nullptr, createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN)};
489 	}
490 	AidlManager* aidl_manager = AidlManager::getInstance();
491 	std::shared_ptr<ISupplicantP2pIface> iface;
492 	if (!aidl_manager ||
493 		aidl_manager->getP2pIfaceAidlObjectByIfname(
494 		wpa_s->ifname, &iface)) {
495 		return {iface, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
496 	}
497 	// Set this flag true here, since there is no AIDL initialize
498 	// method for the p2p config, and the supplicant interface is
499 	// not ready when the p2p iface is created.
500 	wpa_s->conf->persistent_reconnect = true;
501 	return {iface, ndk::ScopedAStatus::ok()};
502 }
503 
504 std::pair<std::shared_ptr<ISupplicantStaIface>, ndk::ScopedAStatus>
getStaInterfaceInternal(const std::string & name)505 Supplicant::getStaInterfaceInternal(const std::string& name)
506 {
507 	struct wpa_supplicant* wpa_s =
508 		wpa_supplicant_get_iface(wpa_global_, name.c_str());
509 	if (!wpa_s) {
510 		return {nullptr, createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN)};
511 	}
512 	AidlManager* aidl_manager = AidlManager::getInstance();
513 	std::shared_ptr<ISupplicantStaIface> iface;
514 	if (!aidl_manager ||
515 		aidl_manager->getStaIfaceAidlObjectByIfname(
516 		wpa_s->ifname, &iface)) {
517 		return {iface, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
518 	}
519 	return {iface, ndk::ScopedAStatus::ok()};
520 }
521 
522 std::pair<std::vector<IfaceInfo>, ndk::ScopedAStatus>
listInterfacesInternal()523 Supplicant::listInterfacesInternal()
524 {
525 	std::vector<IfaceInfo> ifaces;
526 	for (struct wpa_supplicant* wpa_s = wpa_global_->ifaces; wpa_s;
527 		 wpa_s = wpa_s->next) {
528 		if (wpa_s->global->p2p_init_wpa_s == wpa_s) {
529 			ifaces.emplace_back(IfaceInfo{
530 				IfaceType::P2P, wpa_s->ifname});
531 		} else {
532 			ifaces.emplace_back(IfaceInfo{
533 				IfaceType::STA, wpa_s->ifname});
534 		}
535 	}
536 	return {std::move(ifaces), ndk::ScopedAStatus::ok()};
537 }
538 
registerCallbackInternal(const std::shared_ptr<ISupplicantCallback> & callback)539 ndk::ScopedAStatus Supplicant::registerCallbackInternal(
540 	const std::shared_ptr<ISupplicantCallback>& callback)
541 {
542 	AidlManager* aidl_manager = AidlManager::getInstance();
543 	if (!aidl_manager ||
544 		aidl_manager->addSupplicantCallbackAidlObject(callback)) {
545 		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
546 	}
547 	return ndk::ScopedAStatus::ok();
548 }
549 
setDebugParamsInternal(DebugLevel level,bool show_timestamp,bool show_keys)550 ndk::ScopedAStatus Supplicant::setDebugParamsInternal(
551 	DebugLevel level, bool show_timestamp, bool show_keys)
552 {
553 	if (wpa_supplicant_set_debug_params(
554 		wpa_global_, static_cast<uint32_t>(level), show_timestamp,
555 		show_keys)) {
556 		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
557 	}
558 	return ndk::ScopedAStatus::ok();
559 }
560 
setConcurrencyPriorityInternal(IfaceType type)561 ndk::ScopedAStatus Supplicant::setConcurrencyPriorityInternal(IfaceType type)
562 {
563 	if (type == IfaceType::STA) {
564 		wpa_global_->conc_pref =
565 			wpa_global::wpa_conc_pref::WPA_CONC_PREF_STA;
566 	} else if (type == IfaceType::P2P) {
567 		wpa_global_->conc_pref =
568 			wpa_global::wpa_conc_pref::WPA_CONC_PREF_P2P;
569 	} else {
570 		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
571 	}
572 	return ndk::ScopedAStatus::ok();
573 }
574 }  // namespace supplicant
575 }  // namespace wifi
576 }  // namespace hardware
577 }  // namespace android
578 }  // namespace aidl
579