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