Convert supplicant service to use new AIDL interface.
Bug: 196235436
Test: Pass AIDL VTS tests and regression tests.
Change-Id: I0d7b75f526c13fc655a023d7dca088339b06b28e
diff --git a/wpa_supplicant/aidl/.clang-format b/wpa_supplicant/aidl/.clang-format
new file mode 100644
index 0000000..42fadb5
--- /dev/null
+++ b/wpa_supplicant/aidl/.clang-format
@@ -0,0 +1,9 @@
+BasedOnStyle: Google
+IndentWidth: 8
+UseTab: Always
+BreakBeforeBraces: Mozilla
+AllowShortIfStatementsOnASingleLine: false
+IndentCaseLabels: false
+AccessModifierOffset: -8
+AlignAfterOpenBracket: AlwaysBreak
+SortIncludes: false
diff --git a/wpa_supplicant/aidl/Android.bp b/wpa_supplicant/aidl/Android.bp
new file mode 100644
index 0000000..0785fe1
--- /dev/null
+++ b/wpa_supplicant/aidl/Android.bp
@@ -0,0 +1,60 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "external_wpa_supplicant_8_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-BSD
+ default_applicable_licenses: ["external_wpa_supplicant_8_license"],
+}
+
+cc_library_headers {
+ name: "libwpa_aidl_headers",
+ export_include_dirs: ["."],
+ soc_specific: true,
+}
+
+cc_library_static {
+ name: "libwpa_aidl_bp",
+ srcs: ["*.cpp"],
+ defaults: ["wpa_supplicant_cflags_defaults"],
+ soc_specific: true,
+ shared_libs: [
+ "android.hardware.wifi.supplicant-V1-ndk",
+ "libbinder_ndk",
+ "libbase",
+ "libutils",
+ "liblog",
+ "libssl",
+ ],
+ // Generated by building libwpa_hidl and printing LOCAL_CPPFLAGS.
+ cppflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wno-unused-private-field",
+ "-Wno-unused-variable",
+ ],
+ header_libs: [
+ "wpa_supplicant_headers",
+ "libwpa_aidl_headers",
+ ],
+}
+
+filegroup {
+ name: "android.hardware.wifi.supplicant.xml",
+ srcs: ["android.hardware.wifi.supplicant.xml"],
+}
diff --git a/wpa_supplicant/aidl/aidl.cpp b/wpa_supplicant/aidl/aidl.cpp
new file mode 100644
index 0000000..f3f04a3
--- /dev/null
+++ b/wpa_supplicant/aidl/aidl.cpp
@@ -0,0 +1,923 @@
+/*
+ * WPA Supplicant - Aidl entry point to wpa_supplicant core
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include <android/binder_process.h>
+#include <android/binder_manager.h>
+
+#include "aidl_manager.h"
+
+extern "C"
+{
+#include "aidl.h"
+#include "aidl_i.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/includes.h"
+#include "dpp.h"
+}
+
+using aidl::android::hardware::wifi::supplicant::AidlManager;
+using aidl::android::hardware::wifi::supplicant::DppEventType;
+using aidl::android::hardware::wifi::supplicant::DppFailureCode;
+using aidl::android::hardware::wifi::supplicant::DppProgressCode;
+
+static void wpas_aidl_notify_dpp_failure(struct wpa_supplicant *wpa_s, DppFailureCode code);
+static void wpas_aidl_notify_dpp_progress(struct wpa_supplicant *wpa_s, DppProgressCode code);
+static void wpas_aidl_notify_dpp_success(struct wpa_supplicant *wpa_s, DppEventType code);
+
+void wpas_aidl_sock_handler(
+ int /* sock */, void * /* eloop_ctx */, void * /* sock_ctx */)
+{
+ ABinderProcess_handlePolledCommands();
+}
+
+struct wpas_aidl_priv *wpas_aidl_init(struct wpa_global *global)
+{
+ struct wpas_aidl_priv *priv;
+ AidlManager *aidl_manager;
+
+ priv = (wpas_aidl_priv *)os_zalloc(sizeof(*priv));
+ if (!priv)
+ return NULL;
+ priv->global = global;
+
+ wpa_printf(MSG_DEBUG, "Initing aidl control");
+
+ ABinderProcess_setupPolling(&priv->aidl_fd);
+ if (priv->aidl_fd < 0)
+ goto err;
+
+ wpa_printf(MSG_INFO, "Processing aidl events on FD %d", priv->aidl_fd);
+ // Look for read events from the aidl socket in the eloop.
+ if (eloop_register_read_sock(
+ priv->aidl_fd, wpas_aidl_sock_handler, global, priv) < 0)
+ goto err;
+
+ aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ goto err;
+ if (aidl_manager->registerAidlService(global)) {
+ goto err;
+ }
+ // We may not need to store this aidl manager reference in the
+ // global data strucure because we've made it a singleton class.
+ priv->aidl_manager = (void *)aidl_manager;
+
+ return priv;
+err:
+ wpas_aidl_deinit(priv);
+ return NULL;
+}
+
+void wpas_aidl_deinit(struct wpas_aidl_priv *priv)
+{
+ if (!priv)
+ return;
+
+ wpa_printf(MSG_DEBUG, "Deiniting aidl control");
+
+ AidlManager::destroyInstance();
+ eloop_unregister_read_sock(priv->aidl_fd);
+ os_free(priv);
+}
+
+int wpas_aidl_register_interface(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s || !wpa_s->global->aidl)
+ return 1;
+
+ wpa_printf(
+ MSG_DEBUG, "Registering interface to aidl control: %s",
+ wpa_s->ifname);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return 1;
+
+ return aidl_manager->registerInterface(wpa_s);
+}
+
+int wpas_aidl_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s || !wpa_s->global->aidl)
+ return 1;
+
+ wpa_printf(
+ MSG_DEBUG, "Deregistering interface from aidl control: %s",
+ wpa_s->ifname);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return 1;
+
+ return aidl_manager->unregisterInterface(wpa_s);
+}
+
+int wpas_aidl_register_network(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+ if (!wpa_s || !wpa_s->global->aidl || !ssid)
+ return 1;
+
+ wpa_printf(
+ MSG_DEBUG, "Registering network to aidl control: %d", ssid->id);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return 1;
+
+ return aidl_manager->registerNetwork(wpa_s, ssid);
+}
+
+int wpas_aidl_unregister_network(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+ if (!wpa_s || !wpa_s->global->aidl || !ssid)
+ return 1;
+
+ wpa_printf(
+ MSG_DEBUG, "Deregistering network from aidl control: %d", ssid->id);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return 1;
+
+ return aidl_manager->unregisterNetwork(wpa_s, ssid);
+}
+
+int wpas_aidl_notify_state_changed(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s || !wpa_s->global->aidl)
+ return 1;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying state change event to aidl control: %d",
+ wpa_s->wpa_state);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return 1;
+
+ return aidl_manager->notifyStateChange(wpa_s);
+}
+
+int wpas_aidl_notify_network_request(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ enum wpa_ctrl_req_type rtype, const char *default_txt)
+{
+ if (!wpa_s || !wpa_s->global->aidl || !ssid)
+ return 1;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying network request to aidl control: %d",
+ ssid->id);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return 1;
+
+ return aidl_manager->notifyNetworkRequest(
+ wpa_s, ssid, rtype, default_txt);
+}
+
+void wpas_aidl_notify_anqp_query_done(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+ const struct wpa_bss_anqp *anqp)
+{
+ if (!wpa_s || !wpa_s->global->aidl || !bssid || !result || !anqp)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying ANQP query done to aidl control: " MACSTR "result: %s",
+ MAC2STR(bssid), result);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyAnqpQueryDone(wpa_s, bssid, result, anqp);
+}
+
+void wpas_aidl_notify_hs20_icon_query_done(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+ const u8 *image, u32 image_length)
+{
+ if (!wpa_s || !wpa_s->global->aidl || !bssid || !file_name || !image)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying HS20 icon query done to aidl control: " MACSTR
+ "file_name: %s",
+ MAC2STR(bssid), file_name);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyHs20IconQueryDone(
+ wpa_s, bssid, file_name, image, image_length);
+}
+
+void wpas_aidl_notify_hs20_rx_subscription_remediation(
+ struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
+{
+ if (!wpa_s || !wpa_s->global->aidl || !url)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying HS20 subscription remediation rx to aidl control: %s",
+ url);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyHs20RxSubscriptionRemediation(
+ wpa_s, url, osu_method);
+}
+
+void wpas_aidl_notify_hs20_rx_deauth_imminent_notice(
+ struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
+{
+ if (!wpa_s || !wpa_s->global->aidl)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying HS20 deauth imminent notice rx to aidl control: %s",
+ url ? url : "<no URL>");
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyHs20RxDeauthImminentNotice(
+ wpa_s, code, reauth_delay, url);
+}
+
+void wpas_aidl_notify_hs20_rx_terms_and_conditions_acceptance(
+ struct wpa_supplicant *wpa_s, const char *url)
+{
+ if (!wpa_s || !wpa_s->global->aidl || !url)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "Notifying HS20 terms and conditions acceptance rx to aidl control: %s",
+ url);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyHs20RxTermsAndConditionsAcceptance(wpa_s, url);
+}
+
+void wpas_aidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying disconnect reason to aidl control: %d",
+ wpa_s->disconnect_reason);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyDisconnectReason(wpa_s);
+}
+
+void wpas_aidl_notify_assoc_reject(struct wpa_supplicant *wpa_s,
+ const u8 *bssid, u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying assoc reject to aidl control: %d",
+ wpa_s->assoc_status_code);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyAssocReject(wpa_s, bssid, timed_out, assoc_resp_ie, assoc_resp_ie_len);
+}
+
+void wpas_aidl_notify_auth_timeout(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(MSG_DEBUG, "Notifying auth timeout to aidl control");
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyAuthTimeout(wpa_s);
+}
+
+void wpas_aidl_notify_bssid_changed(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(MSG_DEBUG, "Notifying bssid changed to aidl control");
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyBssidChanged(wpa_s);
+}
+
+void wpas_aidl_notify_wps_event_fail(
+ struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+ uint16_t error_indication)
+{
+ if (!wpa_s || !peer_macaddr)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying Wps event fail to aidl control: %d, %d",
+ config_error, error_indication);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyWpsEventFail(
+ wpa_s, peer_macaddr, config_error, error_indication);
+}
+
+void wpas_aidl_notify_wps_event_success(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(MSG_DEBUG, "Notifying Wps event success to aidl control");
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyWpsEventSuccess(wpa_s);
+}
+
+void wpas_aidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying Wps event PBC overlap to aidl control");
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyWpsEventPbcOverlap(wpa_s);
+}
+
+void wpas_aidl_notify_p2p_device_found(
+ struct wpa_supplicant *wpa_s, const u8 *addr,
+ const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+ u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+ u8 peer_wfd_r2_device_info_len)
+{
+ if (!wpa_s || !addr || !info)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying P2P device found to aidl control " MACSTR,
+ MAC2STR(info->p2p_device_addr));
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyP2pDeviceFound(
+ wpa_s, addr, info, peer_wfd_device_info,
+ peer_wfd_device_info_len, peer_wfd_r2_device_info,
+ peer_wfd_r2_device_info_len);
+}
+
+void wpas_aidl_notify_p2p_device_lost(
+ struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
+{
+ if (!wpa_s || !p2p_device_addr)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying P2P device lost to aidl control " MACSTR,
+ MAC2STR(p2p_device_addr));
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyP2pDeviceLost(wpa_s, p2p_device_addr);
+}
+
+void wpas_aidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(MSG_DEBUG, "Notifying P2P find stop to aidl control");
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyP2pFindStopped(wpa_s);
+}
+
+void wpas_aidl_notify_p2p_go_neg_req(
+ struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+ u8 go_intent)
+{
+ if (!wpa_s || !src_addr)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying P2P GO negotiation request to aidl control " MACSTR,
+ MAC2STR(src_addr));
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyP2pGoNegReq(
+ wpa_s, src_addr, dev_passwd_id, go_intent);
+}
+
+void wpas_aidl_notify_p2p_go_neg_completed(
+ struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
+{
+ if (!wpa_s || !res)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying P2P GO negotiation completed to aidl control: %d",
+ res->status);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyP2pGoNegCompleted(wpa_s, res);
+}
+
+void wpas_aidl_notify_p2p_group_formation_failure(
+ struct wpa_supplicant *wpa_s, const char *reason)
+{
+ if (!wpa_s || !reason)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying P2P Group formation failure to aidl control: %s",
+ reason);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyP2pGroupFormationFailure(wpa_s, reason);
+}
+
+void wpas_aidl_notify_p2p_group_started(
+ struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, int persistent,
+ int client)
+{
+ if (!wpa_s || !ssid)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying P2P Group start to aidl control: %d",
+ ssid->id);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyP2pGroupStarted(wpa_s, ssid, persistent, client);
+}
+
+void wpas_aidl_notify_p2p_group_removed(
+ struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, const char *role)
+{
+ if (!wpa_s || !ssid || !role)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG, "Notifying P2P Group removed to aidl control: %d",
+ ssid->id);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyP2pGroupRemoved(wpa_s, ssid, role);
+}
+
+void wpas_aidl_notify_p2p_invitation_received(
+ struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+ const u8 *bssid, int id, int op_freq)
+{
+ if (!wpa_s || !sa || !go_dev_addr || !bssid)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying P2P invitation received to aidl control: %d " MACSTR, id,
+ MAC2STR(bssid));
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyP2pInvitationReceived(
+ wpa_s, sa, go_dev_addr, bssid, id, op_freq);
+}
+
+void wpas_aidl_notify_p2p_invitation_result(
+ struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
+{
+ if (!wpa_s)
+ return;
+ if (bssid) {
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying P2P invitation result to aidl control: " MACSTR,
+ MAC2STR(bssid));
+ } else {
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying P2P invitation result to aidl control: NULL "
+ "bssid");
+ }
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyP2pInvitationResult(wpa_s, status, bssid);
+}
+
+void wpas_aidl_notify_p2p_provision_discovery(
+ struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+ enum p2p_prov_disc_status status, u16 config_methods,
+ unsigned int generated_pin)
+{
+ if (!wpa_s || !dev_addr)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying P2P provision discovery to aidl control " MACSTR,
+ MAC2STR(dev_addr));
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyP2pProvisionDiscovery(
+ wpa_s, dev_addr, request, status, config_methods, generated_pin);
+}
+
+void wpas_aidl_notify_p2p_sd_response(
+ struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+ const u8 *tlvs, size_t tlvs_len)
+{
+ if (!wpa_s || !sa || !tlvs)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying P2P service discovery response to aidl control " MACSTR,
+ MAC2STR(sa));
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyP2pSdResponse(
+ wpa_s, sa, update_indic, tlvs, tlvs_len);
+}
+
+void wpas_aidl_notify_ap_sta_authorized(
+ struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+ if (!wpa_s || !sta)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying P2P AP STA authorized to aidl control " MACSTR,
+ MAC2STR(sta));
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyApStaAuthorized(wpa_s, sta, p2p_dev_addr);
+}
+
+void wpas_aidl_notify_ap_sta_deauthorized(
+ struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+ if (!wpa_s || !sta)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying P2P AP STA deauthorized to aidl control " MACSTR,
+ MAC2STR(sta));
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyApStaDeauthorized(wpa_s, sta, p2p_dev_addr);
+}
+
+void wpas_aidl_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(MSG_DEBUG, "Notifying EAP Error: %d ", error_code);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyEapError(wpa_s, error_code);
+}
+
+void wpas_aidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ if (!wpa_s || !ssid)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying DPP configuration received for SSID %d", ssid->id);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyDppConfigReceived(wpa_s, ssid);
+}
+
+void wpas_aidl_notify_dpp_config_sent(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_success(wpa_s, DppEventType::CONFIGURATION_SENT);
+}
+
+/* DPP Progress notifications */
+void wpas_aidl_notify_dpp_auth_success(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_progress(wpa_s, DppProgressCode::AUTHENTICATION_SUCCESS);
+}
+
+void wpas_aidl_notify_dpp_resp_pending(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_progress(wpa_s, DppProgressCode::RESPONSE_PENDING);
+}
+
+/* DPP Failure notifications */
+void wpas_aidl_notify_dpp_not_compatible(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::NOT_COMPATIBLE);
+}
+
+void wpas_aidl_notify_dpp_missing_auth(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::AUTHENTICATION);
+}
+
+void wpas_aidl_notify_dpp_configuration_failure(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::CONFIGURATION);
+}
+
+void wpas_aidl_notify_dpp_timeout(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::TIMEOUT);
+}
+
+void wpas_aidl_notify_dpp_auth_failure(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::AUTHENTICATION);
+}
+
+void wpas_aidl_notify_dpp_fail(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::FAILURE);
+}
+
+void wpas_aidl_notify_dpp_config_sent_wait_response(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_progress(wpa_s, DppProgressCode::CONFIGURATION_SENT_WAITING_RESPONSE);
+}
+
+/* DPP notification helper functions */
+static void wpas_aidl_notify_dpp_failure(struct wpa_supplicant *wpa_s, DppFailureCode code)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying DPP failure event %d", code);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyDppFailure(wpa_s, code);
+}
+
+static void wpas_aidl_notify_dpp_progress(struct wpa_supplicant *wpa_s, DppProgressCode code)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying DPP progress event %d", code);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyDppProgress(wpa_s, code);
+}
+
+void wpas_aidl_notify_dpp_config_accepted(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_progress(wpa_s, DppProgressCode::CONFIGURATION_ACCEPTED);
+}
+
+static void wpas_aidl_notify_dpp_config_applied(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_success(wpa_s, DppEventType::CONFIGURATION_APPLIED);
+}
+
+static void wpas_aidl_notify_dpp_success(struct wpa_supplicant *wpa_s, DppEventType code)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying DPP progress event %d", code);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyDppSuccess(wpa_s, code);
+}
+
+void wpas_aidl_notify_dpp_config_rejected(struct wpa_supplicant *wpa_s)
+{
+ wpas_aidl_notify_dpp_failure(wpa_s, DppFailureCode::CONFIGURATION_REJECTED);
+}
+
+static void wpas_aidl_notify_dpp_no_ap_failure(struct wpa_supplicant *wpa_s,
+ const char *ssid, const char *channel_list, unsigned short band_list[],
+ int size)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "Notifying DPP NO AP event for SSID %s\nTried channels: %s",
+ ssid ? ssid : "N/A", channel_list ? channel_list : "N/A");
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyDppFailure(wpa_s, DppFailureCode::CANNOT_FIND_NETWORK,
+ ssid, channel_list, band_list, size);
+}
+
+void wpas_aidl_notify_dpp_enrollee_auth_failure(struct wpa_supplicant *wpa_s,
+ const char *ssid, unsigned short band_list[], int size)
+{
+ if (!wpa_s)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "Notifying DPP Enrollee authentication failure, SSID %s",
+ ssid ? ssid : "N/A");
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyDppFailure(wpa_s, DppFailureCode::ENROLLEE_AUTHENTICATION,
+ ssid, NULL, band_list, size);
+}
+
+
+void wpas_aidl_notify_dpp_conn_status(struct wpa_supplicant *wpa_s, enum dpp_status_error status,
+ const char *ssid, const char *channel_list, unsigned short band_list[], int size)
+{
+ switch (status)
+ {
+ case DPP_STATUS_OK:
+ wpas_aidl_notify_dpp_config_applied(wpa_s);
+ break;
+
+ case DPP_STATUS_NO_AP:
+ wpas_aidl_notify_dpp_no_ap_failure(wpa_s, ssid, channel_list, band_list, size);
+ break;
+
+ case DPP_STATUS_AUTH_FAILURE:
+ wpas_aidl_notify_dpp_enrollee_auth_failure(wpa_s, ssid, band_list, size);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void wpas_aidl_notify_pmk_cache_added(
+ struct wpa_supplicant *wpa_s,
+ struct rsn_pmksa_cache_entry *pmksa_entry)
+{
+ if (!wpa_s || !pmksa_entry)
+ return;
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ wpa_printf(
+ MSG_DEBUG,
+ "Notifying PMK cache added event");
+
+ aidl_manager->notifyPmkCacheAdded(wpa_s, pmksa_entry);
+}
+
+void wpas_aidl_notify_bss_tm_status(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ wpa_printf(MSG_DEBUG, "Notifying BSS transition status");
+
+ aidl_manager->notifyBssTmStatus(wpa_s);
+}
+
+void wpas_aidl_notify_transition_disable(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ u8 bitmap)
+{
+ if (!wpa_s || !ssid)
+ return;
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ aidl_manager->notifyTransitionDisable(wpa_s, ssid, bitmap);
+}
+
+void wpas_aidl_notify_network_not_found(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager)
+ return;
+
+ wpa_printf(MSG_DEBUG, "Notify network not found");
+
+ aidl_manager->notifyNetworkNotFound(wpa_s);
+}
diff --git a/wpa_supplicant/aidl/aidl.h b/wpa_supplicant/aidl/aidl.h
new file mode 100644
index 0000000..899f99cd
--- /dev/null
+++ b/wpa_supplicant/aidl/aidl.h
@@ -0,0 +1,286 @@
+/*
+ * WPA Supplicant - Aidl entry point to wpa_supplicant core
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_AIDL_H
+#define WPA_SUPPLICANT_AIDL_AIDL_H
+
+#ifdef _cplusplus
+extern "C"
+{
+#endif // _cplusplus
+
+ /**
+ * This is the aidl RPC interface entry point to the wpa_supplicant
+ * core. This initializes the aidl driver & AidlManager instance and
+ * then forwards all the notifcations from the supplicant core to the
+ * AidlManager.
+ */
+ struct wpas_aidl_priv;
+ struct wpa_global;
+
+ struct wpas_aidl_priv *wpas_aidl_init(struct wpa_global *global);
+ void wpas_aidl_deinit(struct wpas_aidl_priv *priv);
+
+#ifdef CONFIG_CTRL_IFACE_AIDL
+ int wpas_aidl_register_interface(struct wpa_supplicant *wpa_s);
+ int wpas_aidl_unregister_interface(struct wpa_supplicant *wpa_s);
+ int wpas_aidl_register_network(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+ int wpas_aidl_unregister_network(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+ int wpas_aidl_notify_state_changed(struct wpa_supplicant *wpa_s);
+ int wpas_aidl_notify_network_request(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ enum wpa_ctrl_req_type rtype, const char *default_txt);
+ void wpas_aidl_notify_anqp_query_done(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+ const struct wpa_bss_anqp *anqp);
+ void wpas_aidl_notify_hs20_icon_query_done(
+ struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const char *file_name, const u8 *image, u32 image_length);
+ void wpas_aidl_notify_hs20_rx_subscription_remediation(
+ struct wpa_supplicant *wpa_s, const char *url, u8 osu_method);
+ void wpas_aidl_notify_hs20_rx_deauth_imminent_notice(
+ struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay,
+ const char *url);
+ void wpas_aidl_notify_hs20_rx_terms_and_conditions_acceptance(
+ struct wpa_supplicant *wpa_s, const char *url);
+ void wpas_aidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_assoc_reject(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len);
+ void wpas_aidl_notify_auth_timeout(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_bssid_changed(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_wps_event_fail(
+ struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr,
+ uint16_t config_error, uint16_t error_indication);
+ void wpas_aidl_notify_wps_event_success(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_wps_event_pbc_overlap(
+ struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_p2p_device_found(
+ struct wpa_supplicant *wpa_s, const u8 *addr,
+ const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+ u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+ u8 peer_wfd_r2_device_info_len);
+ void wpas_aidl_notify_p2p_device_lost(
+ struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr);
+ void wpas_aidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_p2p_go_neg_req(
+ struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+ u8 go_intent);
+ void wpas_aidl_notify_p2p_go_neg_completed(
+ struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res);
+ void wpas_aidl_notify_p2p_group_formation_failure(
+ struct wpa_supplicant *wpa_s, const char *reason);
+ void wpas_aidl_notify_p2p_group_started(
+ struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid,
+ int persistent, int client);
+ void wpas_aidl_notify_p2p_group_removed(
+ struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid,
+ const char *role);
+ void wpas_aidl_notify_p2p_invitation_received(
+ struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+ const u8 *bssid, int id, int op_freq);
+ void wpas_aidl_notify_p2p_invitation_result(
+ struct wpa_supplicant *wpa_s, int status, const u8 *bssid);
+ void wpas_aidl_notify_p2p_provision_discovery(
+ struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+ enum p2p_prov_disc_status status, u16 config_methods,
+ unsigned int generated_pin);
+ void wpas_aidl_notify_p2p_sd_response(
+ struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+ const u8 *tlvs, size_t tlvs_len);
+ void wpas_aidl_notify_ap_sta_authorized(
+ struct wpa_supplicant *wpa_s, const u8 *sta,
+ const u8 *p2p_dev_addr);
+ void wpas_aidl_notify_ap_sta_deauthorized(
+ struct wpa_supplicant *wpa_s, const u8 *sta,
+ const u8 *p2p_dev_addr);
+ void wpas_aidl_notify_eap_error(
+ struct wpa_supplicant *wpa_s, int error_code);
+ void wpas_aidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
+ void wpas_aidl_notify_dpp_config_sent(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_auth_success(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_resp_pending(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_not_compatible(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_missing_auth(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_configuration_failure(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_invalid_uri(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_timeout(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_auth_failure(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_fail(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_config_sent_wait_response(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_config_accepted(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_config_rejected(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_dpp_conn_status(struct wpa_supplicant *wpa_s,
+ enum dpp_status_error status, const char *ssid,
+ const char *channel_list, unsigned short band_list[], int size);
+ void wpas_aidl_notify_pmk_cache_added(
+ struct wpa_supplicant *wpas, struct rsn_pmksa_cache_entry *pmksa_entry);
+ void wpas_aidl_notify_bss_tm_status(struct wpa_supplicant *wpa_s);
+ void wpas_aidl_notify_transition_disable(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, u8 bitmap);
+ void wpas_aidl_notify_network_not_found(struct wpa_supplicant *wpa_s);
+#else // CONFIG_CTRL_IFACE_AIDL
+static inline int wpas_aidl_register_interface(struct wpa_supplicant *wpa_s)
+{
+ return 0;
+}
+static inline int wpas_aidl_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+ return 0;
+}
+static inline int wpas_aidl_register_network(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+ return 0;
+}
+static inline int wpas_aidl_unregister_network(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+ return 0;
+}
+static inline int wpas_aidl_notify_state_changed(struct wpa_supplicant *wpa_s)
+{
+ return 0;
+}
+static inline int wpas_aidl_notify_network_request(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ enum wpa_ctrl_req_type rtype, const char *default_txt)
+{
+ return 0;
+}
+static void wpas_aidl_notify_anqp_query_done(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+ const struct wpa_bss_anqp *anqp)
+{}
+static void wpas_aidl_notify_hs20_icon_query_done(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+ const u8 *image, u32 image_length)
+{}
+static void wpas_aidl_notify_hs20_rx_subscription_remediation(
+ struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
+{}
+static void wpas_aidl_notify_hs20_rx_deauth_imminent_notice(
+ struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
+{}
+void wpas_aidl_notify_hs20_rx_terms_and_conditions_acceptance(
+ struct wpa_supplicant *wpa_s, const char *url)
+{}
+static void wpas_aidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s) {}
+static void wpas_aidl_notify_assoc_reject(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len) {}
+static void wpas_aidl_notify_auth_timeout(struct wpa_supplicant *wpa_s) {}
+static void wpas_aidl_notify_wps_event_fail(
+ struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+ uint16_t error_indication)
+{}
+static void wpas_aidl_notify_bssid_changed(struct wpa_supplicant *wpa_s) {}
+static void wpas_aidl_notify_wps_event_success(struct wpa_supplicant *wpa_s) {}
+static void wpas_aidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_p2p_device_found(
+ struct wpa_supplicant *wpa_s, const u8 *addr,
+ const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+ u8 peer_wfd_device_info_len)
+{}
+static void wpas_aidl_notify_p2p_device_lost(
+ struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
+{}
+static void wpas_aidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s) {}
+static void wpas_aidl_notify_p2p_go_neg_req(
+ struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+ u8 go_intent)
+{}
+static void wpas_aidl_notify_p2p_go_neg_completed(
+ struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
+{}
+static void wpas_aidl_notify_p2p_group_formation_failure(
+ struct wpa_supplicant *wpa_s, const char *reason)
+{}
+static void wpas_aidl_notify_p2p_group_started(
+ struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, int persistent,
+ int client)
+{}
+static void wpas_aidl_notify_p2p_group_removed(
+ struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, const char *role)
+{}
+static void wpas_aidl_notify_p2p_invitation_received(
+ struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+ const u8 *bssid, int id, int op_freq)
+{}
+static void wpas_aidl_notify_p2p_invitation_result(
+ struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
+{}
+static void wpas_aidl_notify_p2p_provision_discovery(
+ struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+ enum p2p_prov_disc_status status, u16 config_methods,
+ unsigned int generated_pin)
+{}
+static void wpas_aidl_notify_p2p_sd_response(
+ struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+ const u8 *tlvs, size_t tlvs_len)
+{}
+static void wpas_aidl_notify_ap_sta_authorized(
+ struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{}
+static void wpas_aidl_notify_ap_sta_deauthorized(
+ struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{}
+static void wpas_aidl_notify_eap_error(
+ struct wpa_supplicant *wpa_s, int error_code)
+{}
+static void wpas_aidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{}
+static void wpas_aidl_notify_dpp_config_received(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
+static void wpas_aidl_notify_dpp_config_sent(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_auth_success(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_resp_pending(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_not_compatible(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_missing_auth(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_configuration_failure(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_invalid_uri(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_timeout(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_dpp_failure(struct wpa_supplicant *wpa_s)
+{}
+void wpas_aidl_notify_dpp_config_sent_wait_response(struct wpa_supplicant *wpa_s)
+{}
+void wpas_aidl_notify_dpp_config_accepted(struct wpa_supplicant *wpa_s)
+{}
+void wpas_aidl_notify_dpp_config_applied(struct wpa_supplicant *wpa_s)
+{}
+void wpas_aidl_notify_dpp_config_rejected(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_pmk_cache_added(struct wpa_supplicant *wpas,
+ struct rsn_pmksa_cache_entry *pmksa_entry)
+{}
+void wpas_aidl_notify_bss_tm_status(struct wpa_supplicant *wpa_s)
+{}
+static void wpas_aidl_notify_transition_disable(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ u8 bitmap)
+{}
+static void wpas_aidl_notify_network_not_found(struct wpa_supplicant *wpa_s)
+{}
+#endif // CONFIG_CTRL_IFACE_AIDL
+
+#ifdef _cplusplus
+}
+#endif // _cplusplus
+
+#endif // WPA_SUPPLICANT_AIDL_AIDL_H
diff --git a/wpa_supplicant/aidl/aidl_i.h b/wpa_supplicant/aidl/aidl_i.h
new file mode 100644
index 0000000..7f377cd
--- /dev/null
+++ b/wpa_supplicant/aidl/aidl_i.h
@@ -0,0 +1,28 @@
+/*
+ * WPA Supplicant - Global Aidl struct
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef AIDL_I_H
+#define AIDL_I_H
+
+#ifdef _cplusplus
+extern "C"
+{
+#endif // _cplusplus
+
+ struct wpas_aidl_priv
+ {
+ int aidl_fd;
+ struct wpa_global *global;
+ void *aidl_manager;
+ };
+
+#ifdef _cplusplus
+}
+#endif // _cplusplus
+
+#endif // AIDL_I_H
diff --git a/wpa_supplicant/aidl/aidl_manager.cpp b/wpa_supplicant/aidl/aidl_manager.cpp
new file mode 100644
index 0000000..1ce9326
--- /dev/null
+++ b/wpa_supplicant/aidl/aidl_manager.cpp
@@ -0,0 +1,2241 @@
+/*
+ * WPA Supplicant - Manager for Aidl interface objects
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include <algorithm>
+#include <functional>
+#include <iostream>
+#include <regex>
+
+#include "aidl_manager.h"
+#include "misc_utils.h"
+#include <android/binder_process.h>
+#include <android/binder_manager.h>
+
+extern "C" {
+#include "scan.h"
+#include "src/eap_common/eap_sim_common.h"
+#include "list.h"
+}
+
+namespace {
+
+constexpr uint8_t kWfdDeviceInfoLen = 6;
+constexpr uint8_t kWfdR2DeviceInfoLen = 2;
+// GSM-AUTH:<RAND1>:<RAND2>[:<RAND3>]
+constexpr char kGsmAuthRegex2[] = "GSM-AUTH:([0-9a-f]+):([0-9a-f]+)";
+constexpr char kGsmAuthRegex3[] =
+ "GSM-AUTH:([0-9a-f]+):([0-9a-f]+):([0-9a-f]+)";
+// UMTS-AUTH:<RAND>:<AUTN>
+constexpr char kUmtsAuthRegex[] = "UMTS-AUTH:([0-9a-f]+):([0-9a-f]+)";
+constexpr size_t kGsmRandLenBytes = GSM_RAND_LEN;
+constexpr size_t kUmtsRandLenBytes = EAP_AKA_RAND_LEN;
+constexpr size_t kUmtsAutnLenBytes = EAP_AKA_AUTN_LEN;
+const std::vector<uint8_t> kZeroBssid = {0, 0, 0, 0, 0, 0};
+
+using aidl::android::hardware::wifi::supplicant::GsmRand;
+
+/**
+ * Check if the provided |wpa_supplicant| structure represents a P2P iface or
+ * not.
+ */
+constexpr bool isP2pIface(const struct wpa_supplicant *wpa_s)
+{
+ return wpa_s->global->p2p_init_wpa_s == wpa_s;
+}
+
+/**
+ * Creates a unique key for the network using the provided |ifname| and
+ * |network_id| to be used in the internal map of |ISupplicantNetwork| objects.
+ * This is of the form |ifname|_|network_id|. For ex: "wlan0_1".
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ */
+const std::string getNetworkObjectMapKey(
+ const std::string &ifname, int network_id)
+{
+ return ifname + "_" + std::to_string(network_id);
+}
+
+/**
+ * Add callback to the corresponding list after linking to death on the
+ * corresponding aidl object reference.
+ */
+template <class CallbackType>
+int registerForDeathAndAddCallbackAidlObjectToList(
+ AIBinder_DeathRecipient* death_notifier,
+ const std::shared_ptr<CallbackType> &callback,
+ std::vector<std::shared_ptr<CallbackType>> &callback_list)
+{
+ binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
+ death_notifier, nullptr /* cookie */);
+ if (status != STATUS_OK) {
+ wpa_printf(
+ MSG_ERROR,
+ "Error registering for death notification for "
+ "supplicant callback object");
+ return 1;
+ }
+ callback_list.push_back(callback);
+ return 0;
+}
+
+template <class ObjectType>
+int addAidlObjectToMap(
+ const std::string &key, const std::shared_ptr<ObjectType> &object,
+ std::map<const std::string, std::shared_ptr<ObjectType>> &object_map)
+{
+ // Return failure if we already have an object for that |key|.
+ if (object_map.find(key) != object_map.end())
+ return 1;
+ object_map[key] = object;
+ if (!object_map[key].get())
+ return 1;
+ return 0;
+}
+
+template <class ObjectType>
+int removeAidlObjectFromMap(
+ const std::string &key,
+ std::map<const std::string, std::shared_ptr<ObjectType>> &object_map)
+{
+ // Return failure if we dont have an object for that |key|.
+ const auto &object_iter = object_map.find(key);
+ if (object_iter == object_map.end())
+ return 1;
+ object_iter->second->invalidate();
+ object_map.erase(object_iter);
+ return 0;
+}
+
+template <class CallbackType>
+int addIfaceCallbackAidlObjectToMap(
+ AIBinder_DeathRecipient* death_notifier,
+ const std::string &ifname, const std::shared_ptr<CallbackType> &callback,
+ std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+ &callbacks_map)
+{
+ if (ifname.empty())
+ return 1;
+
+ auto iface_callback_map_iter = callbacks_map.find(ifname);
+ if (iface_callback_map_iter == callbacks_map.end())
+ return 1;
+ auto &iface_callback_list = iface_callback_map_iter->second;
+
+ // Register for death notification before we add it to our list.
+ return registerForDeathAndAddCallbackAidlObjectToList<CallbackType>(
+ death_notifier, callback, iface_callback_list);
+}
+
+template <class CallbackType>
+int addNetworkCallbackAidlObjectToMap(
+ AIBinder_DeathRecipient* death_notifier,
+ const std::string &ifname, int network_id,
+ const std::shared_ptr<CallbackType> &callback,
+ std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+ &callbacks_map)
+{
+ if (ifname.empty() || network_id < 0)
+ return 1;
+
+ // Generate the key to be used to lookup the network.
+ const std::string network_key =
+ getNetworkObjectMapKey(ifname, network_id);
+ auto network_callback_map_iter = callbacks_map.find(network_key);
+ if (network_callback_map_iter == callbacks_map.end())
+ return 1;
+ auto &network_callback_list = network_callback_map_iter->second;
+
+ // Register for death notification before we add it to our list.
+ return registerForDeathAndAddCallbackAidlObjectToList<CallbackType>(
+ death_notifier, callback, network_callback_list);
+}
+
+template <class CallbackType>
+int removeAllIfaceCallbackAidlObjectsFromMap(
+ AIBinder_DeathRecipient* death_notifier,
+ const std::string &ifname,
+ std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+ &callbacks_map)
+{
+ auto iface_callback_map_iter = callbacks_map.find(ifname);
+ if (iface_callback_map_iter == callbacks_map.end())
+ return 1;
+ const auto &iface_callback_list = iface_callback_map_iter->second;
+ for (const auto &callback : iface_callback_list) {
+ binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
+ death_notifier, nullptr /* cookie */);
+ if (status != STATUS_OK) {
+ wpa_printf(
+ MSG_ERROR,
+ "Error deregistering for death notification for "
+ "iface callback object");
+ }
+ }
+ callbacks_map.erase(iface_callback_map_iter);
+ return 0;
+}
+
+template <class CallbackType>
+int removeAllNetworkCallbackAidlObjectsFromMap(
+ AIBinder_DeathRecipient* death_notifier,
+ const std::string &network_key,
+ std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+ &callbacks_map)
+{
+ auto network_callback_map_iter = callbacks_map.find(network_key);
+ if (network_callback_map_iter == callbacks_map.end())
+ return 1;
+ const auto &network_callback_list = network_callback_map_iter->second;
+ for (const auto &callback : network_callback_list) {
+ binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
+ death_notifier, nullptr /* cookie */);
+ if (status != STATUS_OK) {
+ wpa_printf(
+ MSG_ERROR,
+ "Error deregistering for death "
+ "notification for "
+ "network callback object");
+ }
+ }
+ callbacks_map.erase(network_callback_map_iter);
+ return 0;
+}
+
+template <class CallbackType>
+void removeIfaceCallbackAidlObjectFromMap(
+ const std::string &ifname, const std::shared_ptr<CallbackType> &callback,
+ std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+ &callbacks_map)
+{
+ if (ifname.empty())
+ return;
+
+ auto iface_callback_map_iter = callbacks_map.find(ifname);
+ if (iface_callback_map_iter == callbacks_map.end())
+ return;
+
+ auto &iface_callback_list = iface_callback_map_iter->second;
+ iface_callback_list.erase(
+ std::remove(
+ iface_callback_list.begin(), iface_callback_list.end(),
+ callback),
+ iface_callback_list.end());
+}
+
+template <class CallbackType>
+void removeNetworkCallbackAidlObjectFromMap(
+ const std::string &ifname, int network_id,
+ const std::shared_ptr<CallbackType> &callback,
+ std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+ &callbacks_map)
+{
+ if (ifname.empty() || network_id < 0)
+ return;
+
+ // Generate the key to be used to lookup the network.
+ const std::string network_key =
+ getNetworkObjectMapKey(ifname, network_id);
+
+ auto network_callback_map_iter = callbacks_map.find(network_key);
+ if (network_callback_map_iter == callbacks_map.end())
+ return;
+
+ auto &network_callback_list = network_callback_map_iter->second;
+ network_callback_list.erase(
+ std::remove(
+ network_callback_list.begin(), network_callback_list.end(),
+ callback),
+ network_callback_list.end());
+}
+
+template <class CallbackType>
+void callWithEachIfaceCallback(
+ const std::string &ifname,
+ const std::function<ndk::ScopedAStatus(std::shared_ptr<CallbackType>)> &method,
+ const std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+ &callbacks_map)
+{
+ if (ifname.empty())
+ return;
+
+ auto iface_callback_map_iter = callbacks_map.find(ifname);
+ if (iface_callback_map_iter == callbacks_map.end())
+ return;
+ const auto &iface_callback_list = iface_callback_map_iter->second;
+ for (const auto &callback : iface_callback_list) {
+ if (!method(callback).isOk()) {
+ wpa_printf(
+ MSG_ERROR, "Failed to invoke AIDL iface callback");
+ }
+ }
+}
+
+template <class CallbackType>
+void callWithEachNetworkCallback(
+ const std::string &ifname, int network_id,
+ const std::function<
+ ndk::ScopedAStatus(std::shared_ptr<CallbackType>)> &method,
+ const std::map<const std::string, std::vector<std::shared_ptr<CallbackType>>>
+ &callbacks_map)
+{
+ if (ifname.empty() || network_id < 0)
+ return;
+
+ // Generate the key to be used to lookup the network.
+ const std::string network_key =
+ getNetworkObjectMapKey(ifname, network_id);
+ auto network_callback_map_iter = callbacks_map.find(network_key);
+ if (network_callback_map_iter == callbacks_map.end())
+ return;
+ const auto &network_callback_list = network_callback_map_iter->second;
+ for (const auto &callback : network_callback_list) {
+ if (!method(callback).isOk()) {
+ wpa_printf(
+ MSG_ERROR,
+ "Failed to invoke AIDL network callback");
+ }
+ }
+}
+
+int parseGsmAuthNetworkRequest(
+ const std::string ¶ms_str,
+ std::vector<GsmRand> *out_rands)
+{
+ std::smatch matches;
+ std::regex params_gsm_regex2(kGsmAuthRegex2);
+ std::regex params_gsm_regex3(kGsmAuthRegex3);
+ if (!std::regex_match(params_str, matches, params_gsm_regex3) &&
+ !std::regex_match(params_str, matches, params_gsm_regex2)) {
+ return 1;
+ }
+ for (uint32_t i = 1; i < matches.size(); i++) {
+ GsmRand rand;
+ rand.data = std::vector<uint8_t>(kGsmRandLenBytes);
+ const auto &match = matches[i];
+ WPA_ASSERT(match.size() >= 2 * rand.data.size());
+ if (hexstr2bin(match.str().c_str(), rand.data.data(), rand.data.size())) {
+ wpa_printf(MSG_ERROR, "Failed to parse GSM auth params");
+ return 1;
+ }
+ out_rands->push_back(rand);
+ }
+ return 0;
+}
+
+int parseUmtsAuthNetworkRequest(
+ const std::string ¶ms_str,
+ std::vector<uint8_t> *out_rand,
+ std::vector<uint8_t> *out_autn)
+{
+ std::smatch matches;
+ std::regex params_umts_regex(kUmtsAuthRegex);
+ if (!std::regex_match(params_str, matches, params_umts_regex)) {
+ return 1;
+ }
+ WPA_ASSERT(matches[1].size() >= 2 * out_rand->size());
+ if (hexstr2bin(
+ matches[1].str().c_str(), out_rand->data(), out_rand->size())) {
+ wpa_printf(MSG_ERROR, "Failed to parse UMTS auth params");
+ return 1;
+ }
+ WPA_ASSERT(matches[2].size() >= 2 * out_autn->size());
+ if (hexstr2bin(
+ matches[2].str().c_str(), out_autn->data(), out_autn->size())) {
+ wpa_printf(MSG_ERROR, "Failed to parse UMTS auth params");
+ return 1;
+ }
+ return 0;
+}
+
+inline std::vector<uint8_t> byteArrToVec(const uint8_t* arr, int len) {
+ return std::vector<uint8_t>{arr, arr + len};
+}
+
+inline std::vector<uint8_t> macAddrToVec(const uint8_t* mac_addr) {
+ return byteArrToVec(mac_addr, ETH_ALEN);
+}
+
+// Raw pointer to the global structure maintained by the core.
+// Declared here to be accessible to onDeath()
+struct wpa_global *wpa_global_;
+
+void onDeath(void* cookie) {
+ wpa_printf(MSG_ERROR, "Client died. Terminating...");
+ wpa_supplicant_terminate_proc(wpa_global_);
+}
+
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+AidlManager *AidlManager::instance_ = NULL;
+
+AidlManager *AidlManager::getInstance()
+{
+ if (!instance_)
+ instance_ = new AidlManager();
+ return instance_;
+}
+
+void AidlManager::destroyInstance()
+{
+ if (instance_)
+ delete instance_;
+ instance_ = NULL;
+}
+
+int AidlManager::registerAidlService(struct wpa_global *global)
+{
+ // Create the main aidl service object and register it.
+ wpa_printf(MSG_INFO, "Starting AIDL supplicant");
+ supplicant_object_ = ndk::SharedRefBase::make<Supplicant>(global);
+ wpa_global_ = global;
+ std::string instance = std::string() + Supplicant::descriptor + "/default";
+ if (AServiceManager_addService(supplicant_object_->asBinder().get(),
+ instance.c_str()) != STATUS_OK)
+ {
+ return 1;
+ }
+
+ // Initialize the death notifier.
+ death_notifier_ = AIBinder_DeathRecipient_new(onDeath);
+ return 0;
+}
+
+/**
+ * Register an interface to aidl manager.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::registerInterface(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return 1;
+
+ if (isP2pIface(wpa_s)) {
+ if (addAidlObjectToMap<P2pIface>(
+ wpa_s->ifname,
+ ndk::SharedRefBase::make<P2pIface>(wpa_s->global, wpa_s->ifname),
+ p2p_iface_object_map_)) {
+ wpa_printf(
+ MSG_ERROR,
+ "Failed to register P2P interface with AIDL "
+ "control: %s",
+ wpa_s->ifname);
+ return 1;
+ }
+ p2p_iface_callbacks_map_[wpa_s->ifname] =
+ std::vector<std::shared_ptr<ISupplicantP2pIfaceCallback>>();
+ } else {
+ if (addAidlObjectToMap<StaIface>(
+ wpa_s->ifname,
+ ndk::SharedRefBase::make<StaIface>(wpa_s->global, wpa_s->ifname),
+ sta_iface_object_map_)) {
+ wpa_printf(
+ MSG_ERROR,
+ "Failed to register STA interface with AIDL "
+ "control: %s",
+ wpa_s->ifname);
+ return 1;
+ }
+ sta_iface_callbacks_map_[wpa_s->ifname] =
+ std::vector<std::shared_ptr<ISupplicantStaIfaceCallback>>();
+ // Turn on Android specific customizations for STA interfaces
+ // here!
+ //
+ // Turn on scan mac randomization only if driver supports.
+ if (wpa_s->mac_addr_rand_supported & MAC_ADDR_RAND_SCAN) {
+ if (wpas_mac_addr_rand_scan_set(
+ wpa_s, MAC_ADDR_RAND_SCAN, nullptr, nullptr)) {
+ wpa_printf(
+ MSG_ERROR,
+ "Failed to enable scan mac randomization");
+ }
+ }
+
+ // Enable randomized source MAC address for GAS/ANQP
+ // Set the lifetime to 0, guarantees a unique address for each GAS
+ // session
+ wpa_s->conf->gas_rand_mac_addr = 1;
+ wpa_s->conf->gas_rand_addr_lifetime = 0;
+ }
+
+ // Invoke the |onInterfaceCreated| method on all registered callbacks.
+ callWithEachSupplicantCallback(std::bind(
+ &ISupplicantCallback::onInterfaceCreated, std::placeholders::_1,
+ misc_utils::charBufToString(wpa_s->ifname)));
+ return 0;
+}
+
+/**
+ * Unregister an interface from aidl manager.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::unregisterInterface(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return 1;
+
+ // Check if this interface is present in P2P map first, else check in
+ // STA map.
+ // Note: We can't use isP2pIface() here because interface
+ // pointers (wpa_s->global->p2p_init_wpa_s == wpa_s) used by the helper
+ // function is cleared by the core before notifying the AIDL interface.
+ bool success =
+ !removeAidlObjectFromMap(wpa_s->ifname, p2p_iface_object_map_);
+ if (success) { // assumed to be P2P
+ success = !removeAllIfaceCallbackAidlObjectsFromMap(
+ death_notifier_, wpa_s->ifname, p2p_iface_callbacks_map_);
+ } else { // assumed to be STA
+ success = !removeAidlObjectFromMap(
+ wpa_s->ifname, sta_iface_object_map_);
+ if (success) {
+ success = !removeAllIfaceCallbackAidlObjectsFromMap(
+ death_notifier_, wpa_s->ifname, sta_iface_callbacks_map_);
+ }
+ }
+ if (!success) {
+ wpa_printf(
+ MSG_ERROR,
+ "Failed to unregister interface with AIDL "
+ "control: %s",
+ wpa_s->ifname);
+ return 1;
+ }
+
+ // Invoke the |onInterfaceRemoved| method on all registered callbacks.
+ callWithEachSupplicantCallback(std::bind(
+ &ISupplicantCallback::onInterfaceRemoved, std::placeholders::_1,
+ misc_utils::charBufToString(wpa_s->ifname)));
+ return 0;
+}
+
+/**
+ * Register a network to aidl manager.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is added.
+ * @param ssid |wpa_ssid| struct corresponding to the network being added.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::registerNetwork(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+ if (!wpa_s || !ssid)
+ return 1;
+
+ // Generate the key to be used to lookup the network.
+ const std::string network_key =
+ getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
+
+ if (isP2pIface(wpa_s)) {
+ if (addAidlObjectToMap<P2pNetwork>(
+ network_key,
+ ndk::SharedRefBase::make<P2pNetwork>(wpa_s->global, wpa_s->ifname, ssid->id),
+ p2p_network_object_map_)) {
+ wpa_printf(
+ MSG_ERROR,
+ "Failed to register P2P network with AIDL "
+ "control: %d",
+ ssid->id);
+ return 1;
+ }
+ } else {
+ if (addAidlObjectToMap<StaNetwork>(
+ network_key,
+ ndk::SharedRefBase::make<StaNetwork>(wpa_s->global, wpa_s->ifname, ssid->id),
+ sta_network_object_map_)) {
+ wpa_printf(
+ MSG_ERROR,
+ "Failed to register STA network with AIDL "
+ "control: %d",
+ ssid->id);
+ return 1;
+ }
+ sta_network_callbacks_map_[network_key] =
+ std::vector<std::shared_ptr<ISupplicantStaNetworkCallback>>();
+ // Invoke the |onNetworkAdded| method on all registered
+ // callbacks.
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback::onNetworkAdded,
+ std::placeholders::_1, ssid->id));
+ }
+ return 0;
+}
+
+/**
+ * Unregister a network from aidl manager.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is added.
+ * @param ssid |wpa_ssid| struct corresponding to the network being added.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::unregisterNetwork(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+ if (!wpa_s || !ssid)
+ return 1;
+
+ // Generate the key to be used to lookup the network.
+ const std::string network_key =
+ getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
+
+ if (isP2pIface(wpa_s)) {
+ if (removeAidlObjectFromMap(
+ network_key, p2p_network_object_map_)) {
+ wpa_printf(
+ MSG_ERROR,
+ "Failed to unregister P2P network with AIDL "
+ "control: %d",
+ ssid->id);
+ return 1;
+ }
+ } else {
+ if (removeAidlObjectFromMap(
+ network_key, sta_network_object_map_)) {
+ wpa_printf(
+ MSG_ERROR,
+ "Failed to unregister STA network with AIDL "
+ "control: %d",
+ ssid->id);
+ return 1;
+ }
+ if (removeAllNetworkCallbackAidlObjectsFromMap(
+ death_notifier_, network_key, sta_network_callbacks_map_)) {
+ return 1;
+ }
+
+ // Invoke the |onNetworkRemoved| method on all registered
+ // callbacks.
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback::onNetworkRemoved,
+ std::placeholders::_1, ssid->id));
+ }
+ return 0;
+}
+
+/**
+ * Notify all listeners about any state changes on a particular interface.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the state change event occured.
+ */
+int AidlManager::notifyStateChange(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return 1;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname) ==
+ sta_iface_object_map_.end())
+ return 1;
+
+ // Invoke the |onStateChanged| method on all registered callbacks.
+ uint32_t aidl_network_id = UINT32_MAX;
+ std::vector<uint8_t> aidl_ssid;
+ if (wpa_s->current_ssid) {
+ aidl_network_id = wpa_s->current_ssid->id;
+ aidl_ssid.assign(
+ wpa_s->current_ssid->ssid,
+ wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
+ }
+ std::vector<uint8_t> bssid;
+ // wpa_supplicant sets the |pending_bssid| field when it starts a
+ // connection. Only after association state does it update the |bssid|
+ // field. So, in the AIDL callback send the appropriate bssid.
+ if (wpa_s->wpa_state <= WPA_ASSOCIATED) {
+ bssid = macAddrToVec(wpa_s->pending_bssid);
+ } else {
+ bssid = macAddrToVec(wpa_s->bssid);
+ }
+ bool fils_hlp_sent =
+ (wpa_auth_alg_fils(wpa_s->auth_alg) &&
+ !dl_list_empty(&wpa_s->fils_hlp_req) &&
+ (wpa_s->wpa_state == WPA_COMPLETED)) ? true : false;
+
+ // Invoke the |onStateChanged| method on all registered callbacks.
+ std::function<
+ ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+ func = std::bind(
+ &ISupplicantStaIfaceCallback::onStateChanged,
+ std::placeholders::_1,
+ static_cast<StaIfaceCallbackState>(
+ wpa_s->wpa_state),
+ bssid, aidl_network_id, aidl_ssid,
+ fils_hlp_sent);
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname), func);
+ return 0;
+}
+
+/**
+ * Notify all listeners about a request on a particular network.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ * @param ssid |wpa_ssid| struct corresponding to the network.
+ * @param type type of request.
+ * @param param addition params associated with the request.
+ */
+int AidlManager::notifyNetworkRequest(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int type,
+ const char *param)
+{
+ if (!wpa_s || !ssid)
+ return 1;
+
+ const std::string network_key =
+ getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
+ if (sta_network_object_map_.find(network_key) ==
+ sta_network_object_map_.end())
+ return 1;
+
+ if (type == WPA_CTRL_REQ_EAP_IDENTITY) {
+ callWithEachStaNetworkCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ ssid->id,
+ std::bind(
+ &ISupplicantStaNetworkCallback::
+ onNetworkEapIdentityRequest,
+ std::placeholders::_1));
+ return 0;
+ }
+ if (type == WPA_CTRL_REQ_SIM) {
+ std::vector<GsmRand> gsm_rands;
+ std::vector<uint8_t> umts_rand = std::vector<uint8_t>(16);
+ std::vector<uint8_t> umts_autn = std::vector<uint8_t>(16);
+ if (!parseGsmAuthNetworkRequest(param, &gsm_rands)) {
+ NetworkRequestEapSimGsmAuthParams aidl_params;
+ aidl_params.rands = gsm_rands;
+ callWithEachStaNetworkCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ ssid->id,
+ std::bind(
+ &ISupplicantStaNetworkCallback::
+ onNetworkEapSimGsmAuthRequest,
+ std::placeholders::_1, aidl_params));
+ return 0;
+ }
+ if (!parseUmtsAuthNetworkRequest(
+ param, &umts_rand, &umts_autn)) {
+ NetworkRequestEapSimUmtsAuthParams aidl_params;
+ aidl_params.rand = umts_rand;
+ aidl_params.autn = umts_autn;
+ callWithEachStaNetworkCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ ssid->id,
+ std::bind(
+ &ISupplicantStaNetworkCallback::
+ onNetworkEapSimUmtsAuthRequest,
+ std::placeholders::_1, aidl_params));
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/**
+ * Notify all listeners about the end of an ANQP query.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param bssid BSSID of the access point.
+ * @param result Result of the operation ("SUCCESS" or "FAILURE").
+ * @param anqp |wpa_bss_anqp| ANQP data fetched.
+ */
+void AidlManager::notifyAnqpQueryDone(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+ const struct wpa_bss_anqp *anqp)
+{
+ if (!wpa_s || !bssid || !result || !anqp)
+ return;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname) ==
+ sta_iface_object_map_.end())
+ return;
+
+ AnqpData aidl_anqp_data;
+ Hs20AnqpData aidl_hs20_anqp_data;
+ if (std::string(result) == "SUCCESS") {
+ aidl_anqp_data.venueName =
+ misc_utils::convertWpaBufToVector(anqp->venue_name);
+ aidl_anqp_data.roamingConsortium =
+ misc_utils::convertWpaBufToVector(anqp->roaming_consortium);
+ aidl_anqp_data.ipAddrTypeAvailability =
+ misc_utils::convertWpaBufToVector(
+ anqp->ip_addr_type_availability);
+ aidl_anqp_data.naiRealm =
+ misc_utils::convertWpaBufToVector(anqp->nai_realm);
+ aidl_anqp_data.anqp3gppCellularNetwork =
+ misc_utils::convertWpaBufToVector(anqp->anqp_3gpp);
+ aidl_anqp_data.domainName =
+ misc_utils::convertWpaBufToVector(anqp->domain_name);
+
+ struct wpa_bss_anqp_elem *elem;
+ dl_list_for_each(elem, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
+ list) {
+ if (elem->infoid == ANQP_VENUE_URL && elem->protected_response) {
+ aidl_anqp_data.venueUrl =
+ misc_utils::convertWpaBufToVector(elem->payload);
+ break;
+ }
+ }
+
+ aidl_hs20_anqp_data.operatorFriendlyName =
+ misc_utils::convertWpaBufToVector(
+ anqp->hs20_operator_friendly_name);
+ aidl_hs20_anqp_data.wanMetrics =
+ misc_utils::convertWpaBufToVector(anqp->hs20_wan_metrics);
+ aidl_hs20_anqp_data.connectionCapability =
+ misc_utils::convertWpaBufToVector(
+ anqp->hs20_connection_capability);
+ aidl_hs20_anqp_data.osuProvidersList =
+ misc_utils::convertWpaBufToVector(
+ anqp->hs20_osu_providers_list);
+ }
+
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname), std::bind(
+ &ISupplicantStaIfaceCallback::onAnqpQueryDone,
+ std::placeholders::_1, macAddrToVec(bssid), aidl_anqp_data,
+ aidl_hs20_anqp_data));
+}
+
+/**
+ * Notify all listeners about the end of an HS20 icon query.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param bssid BSSID of the access point.
+ * @param file_name Name of the icon file.
+ * @param image Raw bytes of the icon file.
+ * @param image_length Size of the the icon file.
+ */
+void AidlManager::notifyHs20IconQueryDone(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+ const u8 *image, u32 image_length)
+{
+ if (!wpa_s || !bssid || !file_name || !image)
+ return;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname) ==
+ sta_iface_object_map_.end())
+ return;
+
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback::onHs20IconQueryDone,
+ std::placeholders::_1, macAddrToVec(bssid), file_name,
+ std::vector<uint8_t>(image, image + image_length)));
+}
+
+/**
+ * Notify all listeners about the reception of HS20 subscription
+ * remediation notification from the server.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param url URL of the server.
+ * @param osu_method OSU method (OMA_DM or SOAP_XML_SPP).
+ */
+void AidlManager::notifyHs20RxSubscriptionRemediation(
+ struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
+{
+ if (!wpa_s || !url)
+ return;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname) ==
+ sta_iface_object_map_.end())
+ return;
+
+ OsuMethod aidl_osu_method;
+ if (osu_method & 0x1) {
+ aidl_osu_method = OsuMethod::OMA_DM;
+ } else if (osu_method & 0x2) {
+ aidl_osu_method = OsuMethod::SOAP_XML_SPP;
+ }
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback::onHs20SubscriptionRemediation,
+ std::placeholders::_1, macAddrToVec(wpa_s->bssid), aidl_osu_method, url));
+}
+
+/**
+ * Notify all listeners about the reception of HS20 imminent death
+ * notification from the server.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param code Death reason code sent from server.
+ * @param reauth_delay Reauthentication delay in seconds sent from server.
+ * @param url URL of the server containing the reason text.
+ */
+void AidlManager::notifyHs20RxDeauthImminentNotice(
+ struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
+{
+ if (!wpa_s)
+ return;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname) ==
+ sta_iface_object_map_.end())
+ return;
+
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback::onHs20DeauthImminentNotice,
+ std::placeholders::_1, macAddrToVec(wpa_s->bssid), code,
+ reauth_delay, misc_utils::charBufToString(url)));
+}
+
+/**
+ * Notify all listeners about the reception of HS20 terms and conditions
+ * acceptance notification from the server.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param url URL of the T&C server.
+ */
+void AidlManager::notifyHs20RxTermsAndConditionsAcceptance(
+ struct wpa_supplicant *wpa_s, const char *url)
+{
+ if (!wpa_s || !url)
+ return;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname)
+ == sta_iface_object_map_.end())
+ return;
+
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback
+ ::onHs20TermsAndConditionsAcceptanceRequestedNotification,
+ std::placeholders::_1, macAddrToVec(wpa_s->bssid), url));
+}
+
+/**
+ * Notify all listeners about the reason code for disconnection from the
+ * currently connected network.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ */
+void AidlManager::notifyDisconnectReason(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname) ==
+ sta_iface_object_map_.end())
+ return;
+
+ const u8 *bssid = wpa_s->bssid;
+ if (is_zero_ether_addr(bssid)) {
+ bssid = wpa_s->pending_bssid;
+ }
+
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback::onDisconnected,
+ std::placeholders::_1, macAddrToVec(bssid), wpa_s->disconnect_reason < 0,
+ static_cast<StaIfaceReasonCode>(
+ abs(wpa_s->disconnect_reason))));
+}
+
+/**
+ * Notify all listeners about association reject from the access point to which
+ * we are attempting to connect.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ * @param bssid bssid of AP that rejected the association.
+ * @param timed_out flag to indicate failure is due to timeout
+ * (auth, assoc, ...) rather than explicit rejection response from the AP.
+ * @param assoc_resp_ie Association response IE.
+ * @param assoc_resp_ie_len Association response IE length.
+ */
+void AidlManager::notifyAssocReject(struct wpa_supplicant *wpa_s,
+ const u8 *bssid, u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len)
+{
+ std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+#ifdef CONFIG_MBO
+ struct wpa_bss *reject_bss;
+#endif /* CONFIG_MBO */
+ AssociationRejectionData aidl_assoc_reject_data{};
+
+ if (!wpa_s)
+ return;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname) ==
+ sta_iface_object_map_.end())
+ return;
+ if (wpa_s->current_ssid) {
+ aidl_assoc_reject_data.ssid = std::vector<uint8_t>(
+ wpa_s->current_ssid->ssid,
+ wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
+ }
+ aidl_assoc_reject_data.bssid = macAddrToVec(bssid);
+ aidl_assoc_reject_data.statusCode = static_cast<StaIfaceStatusCode>(
+ wpa_s->assoc_status_code);
+ if (timed_out) {
+ aidl_assoc_reject_data.timedOut = true;
+ }
+#ifdef CONFIG_MBO
+ if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
+ reject_bss = wpa_s->current_bss;
+ } else {
+ reject_bss = wpa_bss_get_bssid(wpa_s, bssid);
+ }
+ if (reject_bss && assoc_resp_ie && assoc_resp_ie_len > 0) {
+ if (wpa_s->assoc_status_code ==
+ WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS) {
+ const u8 *rssi_rej;
+ rssi_rej = mbo_get_attr_from_ies(
+ assoc_resp_ie,
+ assoc_resp_ie_len,
+ OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT);
+ if (rssi_rej && rssi_rej[1] == 2) {
+ wpa_printf(MSG_INFO,
+ "OCE: RSSI-based association rejection from "
+ MACSTR " Delta RSSI: %u, Retry Delay: %u bss rssi: %d",
+ MAC2STR(reject_bss->bssid),
+ rssi_rej[2], rssi_rej[3], reject_bss->level);
+ aidl_assoc_reject_data.isOceRssiBasedAssocRejectAttrPresent = true;
+ aidl_assoc_reject_data.oceRssiBasedAssocRejectData.deltaRssi
+ = rssi_rej[2];
+ aidl_assoc_reject_data.oceRssiBasedAssocRejectData.retryDelayS
+ = rssi_rej[3];
+ }
+ } else if (wpa_s->assoc_status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY
+ || wpa_s->assoc_status_code == WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA) {
+ const u8 *assoc_disallowed;
+ assoc_disallowed = mbo_get_attr_from_ies(
+ assoc_resp_ie,
+ assoc_resp_ie_len,
+ MBO_ATTR_ID_ASSOC_DISALLOW);
+ if (assoc_disallowed && assoc_disallowed[1] == 1) {
+ wpa_printf(MSG_INFO,
+ "MBO: association disallowed indication from "
+ MACSTR " Reason: %d",
+ MAC2STR(reject_bss->bssid),
+ assoc_disallowed[2]);
+ aidl_assoc_reject_data.isMboAssocDisallowedReasonCodePresent = true;
+ aidl_assoc_reject_data.mboAssocDisallowedReason
+ = static_cast<MboAssocDisallowedReasonCode>(assoc_disallowed[2]);
+ }
+ }
+ }
+#endif /* CONFIG_MBO */
+
+ const std::function<
+ ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+ func = std::bind(
+ &ISupplicantStaIfaceCallback::onAssociationRejected,
+ std::placeholders::_1, aidl_assoc_reject_data);
+ callWithEachStaIfaceCallback(aidl_ifname, func);
+}
+
+void AidlManager::notifyAuthTimeout(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ const std::string ifname(wpa_s->ifname);
+ if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+ return;
+
+ const u8 *bssid = wpa_s->bssid;
+ if (is_zero_ether_addr(bssid)) {
+ bssid = wpa_s->pending_bssid;
+ }
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback::onAuthenticationTimeout,
+ std::placeholders::_1, macAddrToVec(bssid)));
+}
+
+void AidlManager::notifyBssidChanged(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ const std::string ifname(wpa_s->ifname);
+ if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+ return;
+
+ // wpa_supplicant does not explicitly give us the reason for bssid
+ // change, but we figure that out from what is set out of |wpa_s->bssid|
+ // & |wpa_s->pending_bssid|.
+ const u8 *bssid;
+ BssidChangeReason reason;
+ if (is_zero_ether_addr(wpa_s->bssid) &&
+ !is_zero_ether_addr(wpa_s->pending_bssid)) {
+ bssid = wpa_s->pending_bssid;
+ reason = BssidChangeReason::ASSOC_START;
+ } else if (
+ !is_zero_ether_addr(wpa_s->bssid) &&
+ is_zero_ether_addr(wpa_s->pending_bssid)) {
+ bssid = wpa_s->bssid;
+ reason = BssidChangeReason::ASSOC_COMPLETE;
+ } else if (
+ is_zero_ether_addr(wpa_s->bssid) &&
+ is_zero_ether_addr(wpa_s->pending_bssid)) {
+ bssid = wpa_s->pending_bssid;
+ reason = BssidChangeReason::DISASSOC;
+ } else {
+ wpa_printf(MSG_ERROR, "Unknown bssid change reason");
+ return;
+ }
+
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname), std::bind(
+ &ISupplicantStaIfaceCallback::onBssidChanged,
+ std::placeholders::_1, reason, macAddrToVec(bssid)));
+}
+
+void AidlManager::notifyWpsEventFail(
+ struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+ uint16_t error_indication)
+{
+ if (!wpa_s || !peer_macaddr)
+ return;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname) ==
+ sta_iface_object_map_.end())
+ return;
+
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback::onWpsEventFail,
+ std::placeholders::_1, macAddrToVec(peer_macaddr),
+ static_cast<WpsConfigError>(
+ config_error),
+ static_cast<WpsErrorIndication>(
+ error_indication)));
+}
+
+void AidlManager::notifyWpsEventSuccess(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname) ==
+ sta_iface_object_map_.end())
+ return;
+
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname), std::bind(
+ &ISupplicantStaIfaceCallback::onWpsEventSuccess,
+ std::placeholders::_1));
+}
+
+void AidlManager::notifyWpsEventPbcOverlap(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname) ==
+ sta_iface_object_map_.end())
+ return;
+
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback::onWpsEventPbcOverlap,
+ std::placeholders::_1));
+}
+
+void AidlManager::notifyP2pDeviceFound(
+ struct wpa_supplicant *wpa_s, const u8 *addr,
+ const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+ u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+ u8 peer_wfd_r2_device_info_len)
+{
+ if (!wpa_s || !addr || !info)
+ return;
+
+ if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+ p2p_iface_object_map_.end())
+ return;
+
+ std::vector<uint8_t> aidl_peer_wfd_device_info(kWfdDeviceInfoLen);
+ if (peer_wfd_device_info) {
+ if (peer_wfd_device_info_len != kWfdDeviceInfoLen) {
+ wpa_printf(
+ MSG_ERROR, "Unexpected WFD device info len: %d",
+ peer_wfd_device_info_len);
+ } else {
+ os_memcpy(
+ aidl_peer_wfd_device_info.data(),
+ peer_wfd_device_info, kWfdDeviceInfoLen);
+ }
+ }
+
+ std::vector<uint8_t> aidl_peer_wfd_r2_device_info(kWfdR2DeviceInfoLen);
+ if (peer_wfd_r2_device_info) {
+ if (peer_wfd_r2_device_info_len != kWfdR2DeviceInfoLen) {
+ wpa_printf(
+ MSG_ERROR, "Unexpected WFD R2 device info len: %d",
+ peer_wfd_r2_device_info_len);
+ return;
+ } else {
+ os_memcpy(
+ aidl_peer_wfd_r2_device_info.data(),
+ peer_wfd_r2_device_info, kWfdR2DeviceInfoLen);
+ }
+ }
+
+ if (peer_wfd_r2_device_info_len == kWfdR2DeviceInfoLen) {
+ const std::function<
+ ndk::ScopedAStatus(std::shared_ptr<ISupplicantP2pIfaceCallback>)>
+ func = std::bind(
+ &ISupplicantP2pIfaceCallback::onR2DeviceFound,
+ std::placeholders::_1, macAddrToVec(addr), macAddrToVec(info->p2p_device_addr),
+ byteArrToVec(info->pri_dev_type, 8), misc_utils::charBufToString(info->device_name),
+ static_cast<WpsConfigMethods>(info->config_methods),
+ info->dev_capab, static_cast<P2pGroupCapabilityMask>(info->group_capab), aidl_peer_wfd_device_info,
+ aidl_peer_wfd_r2_device_info);
+ callWithEachP2pIfaceCallback(misc_utils::charBufToString(wpa_s->ifname), func);
+ } else {
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantP2pIfaceCallback::onDeviceFound,
+ std::placeholders::_1, macAddrToVec(addr), macAddrToVec(info->p2p_device_addr),
+ byteArrToVec(info->pri_dev_type, 8), misc_utils::charBufToString(info->device_name),
+ static_cast<WpsConfigMethods>(info->config_methods),
+ info->dev_capab, static_cast<P2pGroupCapabilityMask>(info->group_capab), aidl_peer_wfd_device_info));
+ }
+}
+
+void AidlManager::notifyP2pDeviceLost(
+ struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
+{
+ if (!wpa_s || !p2p_device_addr)
+ return;
+
+ if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+ p2p_iface_object_map_.end())
+ return;
+
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname), std::bind(
+ &ISupplicantP2pIfaceCallback::onDeviceLost,
+ std::placeholders::_1, macAddrToVec(p2p_device_addr)));
+}
+
+void AidlManager::notifyP2pFindStopped(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return;
+
+ if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+ p2p_iface_object_map_.end())
+ return;
+
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname), std::bind(
+ &ISupplicantP2pIfaceCallback::onFindStopped,
+ std::placeholders::_1));
+}
+
+void AidlManager::notifyP2pGoNegReq(
+ struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+ u8 /* go_intent */)
+{
+ if (!wpa_s || !src_addr)
+ return;
+
+ if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+ p2p_iface_object_map_.end())
+ return;
+
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantP2pIfaceCallback::onGoNegotiationRequest,
+ std::placeholders::_1, macAddrToVec(src_addr),
+ static_cast<WpsDevPasswordId>(
+ dev_passwd_id)));
+}
+
+void AidlManager::notifyP2pGoNegCompleted(
+ struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
+{
+ if (!wpa_s || !res)
+ return;
+
+ if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+ p2p_iface_object_map_.end())
+ return;
+
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantP2pIfaceCallback::onGoNegotiationCompleted,
+ std::placeholders::_1,
+ static_cast<P2pStatusCode>(
+ res->status)));
+}
+
+void AidlManager::notifyP2pGroupFormationFailure(
+ struct wpa_supplicant *wpa_s, const char *reason)
+{
+ if (!wpa_s || !reason)
+ return;
+
+ if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+ p2p_iface_object_map_.end())
+ return;
+
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantP2pIfaceCallback::onGroupFormationFailure,
+ std::placeholders::_1, reason));
+}
+
+void AidlManager::notifyP2pGroupStarted(
+ struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
+ int persistent, int client)
+{
+ if (!wpa_group_s || !wpa_group_s->parent || !ssid)
+ return;
+
+ // For group notifications, need to use the parent iface for callbacks.
+ struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+ if (!wpa_s)
+ return;
+
+ uint32_t aidl_freq = wpa_group_s->current_bss
+ ? wpa_group_s->current_bss->freq
+ : wpa_group_s->assoc_freq;
+ std::vector<uint8_t> aidl_psk(32);
+ if (ssid->psk_set) {
+ aidl_psk.assign(ssid->psk, ssid->psk + 32);
+ }
+ bool aidl_is_go = (client == 0 ? true : false);
+ bool aidl_is_persistent = (persistent == 1 ? true : false);
+
+ // notify the group device again to ensure the framework knowing this device.
+ struct p2p_data *p2p = wpa_s->global->p2p;
+ struct p2p_device *dev = p2p_get_device(p2p, wpa_group_s->go_dev_addr);
+ if (NULL != dev) {
+ wpa_printf(MSG_DEBUG, "P2P: Update GO device on group started.");
+ p2p->cfg->dev_found(p2p->cfg->cb_ctx, wpa_group_s->go_dev_addr,
+ &dev->info, !(dev->flags & P2P_DEV_REPORTED_ONCE));
+ dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
+ }
+
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantP2pIfaceCallback::onGroupStarted,
+ std::placeholders::_1, misc_utils::charBufToString(wpa_group_s->ifname),
+ aidl_is_go, byteArrToVec(ssid->ssid, ssid->ssid_len),
+ aidl_freq, aidl_psk, misc_utils::charBufToString(ssid->passphrase),
+ macAddrToVec(wpa_group_s->go_dev_addr), aidl_is_persistent));
+}
+
+void AidlManager::notifyP2pGroupRemoved(
+ struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
+ const char *role)
+{
+ if (!wpa_group_s || !wpa_group_s->parent || !ssid || !role)
+ return;
+
+ // For group notifications, need to use the parent iface for callbacks.
+ struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+ if (!wpa_s)
+ return;
+
+ bool aidl_is_go = (std::string(role) == "GO");
+
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantP2pIfaceCallback::onGroupRemoved,
+ std::placeholders::_1, misc_utils::charBufToString(wpa_group_s->ifname), aidl_is_go));
+}
+
+void AidlManager::notifyP2pInvitationReceived(
+ struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+ const u8 *bssid, int id, int op_freq)
+{
+ if (!wpa_s || !sa || !go_dev_addr || !bssid)
+ return;
+
+ if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+ p2p_iface_object_map_.end())
+ return;
+
+ int aidl_network_id;
+ if (id < 0) {
+ aidl_network_id = UINT32_MAX;
+ }
+ aidl_network_id = id;
+
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantP2pIfaceCallback::onInvitationReceived,
+ std::placeholders::_1, macAddrToVec(sa), macAddrToVec(go_dev_addr),
+ macAddrToVec(bssid), aidl_network_id, op_freq));
+}
+
+void AidlManager::notifyP2pInvitationResult(
+ struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
+{
+ if (!wpa_s)
+ return;
+
+ if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+ p2p_iface_object_map_.end())
+ return;
+
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantP2pIfaceCallback::onInvitationResult,
+ std::placeholders::_1, bssid ? macAddrToVec(bssid) : kZeroBssid,
+ static_cast<P2pStatusCode>(
+ status)));
+}
+
+void AidlManager::notifyP2pProvisionDiscovery(
+ struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+ enum p2p_prov_disc_status status, u16 config_methods,
+ unsigned int generated_pin)
+{
+ if (!wpa_s || !dev_addr)
+ return;
+
+ if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+ p2p_iface_object_map_.end())
+ return;
+
+ std::string aidl_generated_pin;
+ if (generated_pin > 0) {
+ aidl_generated_pin =
+ misc_utils::convertWpsPinToString(generated_pin);
+ }
+ bool aidl_is_request = (request == 1 ? true : false);
+
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantP2pIfaceCallback::onProvisionDiscoveryCompleted,
+ std::placeholders::_1, macAddrToVec(dev_addr), aidl_is_request,
+ static_cast<P2pProvDiscStatusCode>(status),
+ static_cast<WpsConfigMethods>(config_methods), aidl_generated_pin));
+}
+
+void AidlManager::notifyP2pSdResponse(
+ struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+ const u8 *tlvs, size_t tlvs_len)
+{
+ if (!wpa_s || !sa || !tlvs)
+ return;
+
+ if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+ p2p_iface_object_map_.end())
+ return;
+
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantP2pIfaceCallback::onServiceDiscoveryResponse,
+ std::placeholders::_1, macAddrToVec(sa), update_indic,
+ byteArrToVec(tlvs, tlvs_len)));
+}
+
+void AidlManager::notifyApStaAuthorized(
+ struct wpa_supplicant *wpa_group_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+ if (!wpa_group_s || !wpa_group_s->parent || !sta)
+ return;
+ wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+ if (!wpa_s)
+ return;
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantP2pIfaceCallback::onStaAuthorized,
+ std::placeholders::_1, macAddrToVec(sta),
+ p2p_dev_addr ? macAddrToVec(p2p_dev_addr) : kZeroBssid));
+}
+
+void AidlManager::notifyApStaDeauthorized(
+ struct wpa_supplicant *wpa_group_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+ if (!wpa_group_s || !wpa_group_s->parent || !sta)
+ return;
+ wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+ if (!wpa_s)
+ return;
+
+ callWithEachP2pIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantP2pIfaceCallback::onStaDeauthorized,
+ std::placeholders::_1, macAddrToVec(sta),
+ p2p_dev_addr ? macAddrToVec(p2p_dev_addr) : kZeroBssid));
+}
+
+void AidlManager::notifyExtRadioWorkStart(
+ struct wpa_supplicant *wpa_s, uint32_t id)
+{
+ if (!wpa_s)
+ return;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname) ==
+ sta_iface_object_map_.end())
+ return;
+
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback::onExtRadioWorkStart,
+ std::placeholders::_1, id));
+}
+
+void AidlManager::notifyExtRadioWorkTimeout(
+ struct wpa_supplicant *wpa_s, uint32_t id)
+{
+ if (!wpa_s)
+ return;
+
+ if (sta_iface_object_map_.find(wpa_s->ifname) ==
+ sta_iface_object_map_.end())
+ return;
+
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback::onExtRadioWorkTimeout,
+ std::placeholders::_1, id));
+}
+
+void AidlManager::notifyEapError(struct wpa_supplicant *wpa_s, int error_code)
+{
+ if (!wpa_s)
+ return;
+
+ callWithEachStaIfaceCallback(
+ misc_utils::charBufToString(wpa_s->ifname),
+ std::bind(
+ &ISupplicantStaIfaceCallback::onEapFailure,
+ std::placeholders::_1, error_code));
+}
+
+/**
+ * Notify listener about a new DPP configuration received success event
+ *
+ * @param ifname Interface name
+ * @param config Configuration object
+ */
+void AidlManager::notifyDppConfigReceived(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *config)
+{
+ DppAkm securityAkm;
+ std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+
+ if ((config->key_mgmt & WPA_KEY_MGMT_SAE) &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) {
+ securityAkm = DppAkm::SAE;
+ } else if (config->key_mgmt & WPA_KEY_MGMT_PSK) {
+ securityAkm = DppAkm::PSK;
+ } else {
+ /* Unsupported AKM */
+ wpa_printf(MSG_ERROR, "DPP: Error: Unsupported AKM 0x%X",
+ config->key_mgmt);
+ notifyDppFailure(wpa_s, DppFailureCode::NOT_SUPPORTED);
+ return;
+ }
+
+ std::string passphrase = misc_utils::charBufToString(config->passphrase);
+ std::vector<uint8_t> aidl_ssid(
+ config->ssid,
+ config->ssid + config->ssid_len);
+
+ /* At this point, the network is already registered, notify about new
+ * received configuration
+ */
+ callWithEachStaIfaceCallback(aidl_ifname,
+ std::bind(
+ &ISupplicantStaIfaceCallback::onDppSuccessConfigReceived,
+ std::placeholders::_1, aidl_ssid, passphrase,
+ byteArrToVec(config->psk, 32), securityAkm));
+}
+
+/**
+ * Notify listener about a DPP configuration sent success event
+ *
+ * @param ifname Interface name
+ */
+void AidlManager::notifyDppConfigSent(struct wpa_supplicant *wpa_s)
+{
+ std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+
+ callWithEachStaIfaceCallback(aidl_ifname,
+ std::bind(&ISupplicantStaIfaceCallback::onDppSuccessConfigSent,
+ std::placeholders::_1));
+}
+
+/**
+ * Notify listener about a DPP failure event
+ *
+ * @param ifname Interface name
+ * @param code Status code
+ */
+void AidlManager::notifyDppFailure(struct wpa_supplicant *wpa_s,
+ android::hardware::wifi::supplicant::DppFailureCode code) {
+ notifyDppFailure(wpa_s, code, NULL, NULL, NULL, 0);
+}
+
+/**
+ * Notify listener about a DPP failure event
+ *
+ * @param ifname Interface name
+ * @param code Status code
+ */
+void AidlManager::notifyDppFailure(struct wpa_supplicant *wpa_s,
+ DppFailureCode code, const char *ssid, const char *channel_list,
+ unsigned short band_list[], int size) {
+ std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+ std::vector<char16_t> band_list_vec(band_list, band_list + size);
+
+ callWithEachStaIfaceCallback(aidl_ifname,
+ std::bind(&ISupplicantStaIfaceCallback::onDppFailure,
+ std::placeholders::_1, code, misc_utils::charBufToString(ssid),
+ misc_utils::charBufToString(channel_list), band_list_vec));
+}
+
+/**
+ * Notify listener about a DPP progress event
+ *
+ * @param ifname Interface name
+ * @param code Status code
+ */
+void AidlManager::notifyDppProgress(
+ struct wpa_supplicant *wpa_s, DppProgressCode code) {
+ std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+
+ callWithEachStaIfaceCallback(aidl_ifname,
+ std::bind(&ISupplicantStaIfaceCallback::onDppProgress,
+ std::placeholders::_1, code));
+}
+
+/**
+ * Notify listener about a DPP success event
+ *
+ * @param ifname Interface name
+ * @param code Status code
+ */
+void AidlManager::notifyDppSuccess(struct wpa_supplicant *wpa_s, DppEventType code)
+{
+ std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+
+ callWithEachStaIfaceCallback(aidl_ifname,
+ std::bind(&ISupplicantStaIfaceCallback::onDppSuccess,
+ std::placeholders::_1, code));
+}
+
+/**
+ * Notify listener about a PMK cache added event
+ *
+ * @param ifname Interface name
+ * @param entry PMK cache entry
+ */
+void AidlManager::notifyPmkCacheAdded(
+ struct wpa_supplicant *wpa_s, struct rsn_pmksa_cache_entry *pmksa_entry)
+{
+ std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+
+ // Serialize PmkCacheEntry into blob.
+ std::stringstream ss(
+ std::stringstream::in | std::stringstream::out | std::stringstream::binary);
+ misc_utils::serializePmkCacheEntry(ss, pmksa_entry);
+ std::vector<uint8_t> serializedEntry(
+ std::istreambuf_iterator<char>(ss), {});
+
+ const std::function<
+ ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+ func = std::bind(
+ &ISupplicantStaIfaceCallback::onPmkCacheAdded,
+ std::placeholders::_1, pmksa_entry->expiration, serializedEntry);
+ callWithEachStaIfaceCallback(aidl_ifname, func);
+}
+
+#ifdef CONFIG_WNM
+BssTmStatusCode convertSupplicantBssTmStatusToAidl(
+ enum bss_trans_mgmt_status_code bss_tm_status)
+{
+ switch (bss_tm_status) {
+ case WNM_BSS_TM_ACCEPT:
+ return BssTmStatusCode::ACCEPT;
+ case WNM_BSS_TM_REJECT_UNSPECIFIED:
+ return BssTmStatusCode::REJECT_UNSPECIFIED;
+ case WNM_BSS_TM_REJECT_INSUFFICIENT_BEACON:
+ return BssTmStatusCode::REJECT_INSUFFICIENT_BEACON;
+ case WNM_BSS_TM_REJECT_INSUFFICIENT_CAPABITY:
+ return BssTmStatusCode::REJECT_INSUFFICIENT_CAPABITY;
+ case WNM_BSS_TM_REJECT_UNDESIRED:
+ return BssTmStatusCode::REJECT_BSS_TERMINATION_UNDESIRED;
+ case WNM_BSS_TM_REJECT_DELAY_REQUEST:
+ return BssTmStatusCode::REJECT_BSS_TERMINATION_DELAY_REQUEST;
+ case WNM_BSS_TM_REJECT_STA_CANDIDATE_LIST_PROVIDED:
+ return BssTmStatusCode::REJECT_STA_CANDIDATE_LIST_PROVIDED;
+ case WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES:
+ return BssTmStatusCode::REJECT_NO_SUITABLE_CANDIDATES;
+ case WNM_BSS_TM_REJECT_LEAVING_ESS:
+ return BssTmStatusCode::REJECT_LEAVING_ESS;
+ default:
+ return BssTmStatusCode::REJECT_UNSPECIFIED;
+ }
+}
+
+BssTmDataFlagsMask setBssTmDataFlagsMask(struct wpa_supplicant *wpa_s)
+{
+ uint32_t flags = 0;
+
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
+ flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_BSS_TERMINATION_INCLUDED);
+ }
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT) {
+ flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_ESS_DISASSOCIATION_IMMINENT);
+ }
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
+ flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_DISASSOCIATION_IMMINENT);
+ }
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ABRIDGED) {
+ flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_ABRIDGED);
+ }
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED) {
+ flags |= static_cast<uint32_t>(BssTmDataFlagsMask::WNM_MODE_PREFERRED_CANDIDATE_LIST_INCLUDED);
+ }
+#ifdef CONFIG_MBO
+ if (wpa_s->wnm_mbo_assoc_retry_delay_present) {
+ flags |= static_cast<uint32_t>(BssTmDataFlagsMask::MBO_ASSOC_RETRY_DELAY_INCLUDED);
+ }
+ if (wpa_s->wnm_mbo_trans_reason_present) {
+ flags |= static_cast<uint32_t>(BssTmDataFlagsMask::MBO_TRANSITION_REASON_CODE_INCLUDED);
+ }
+ if (wpa_s->wnm_mbo_cell_pref_present) {
+ flags |= static_cast<uint32_t>(BssTmDataFlagsMask::MBO_CELLULAR_DATA_CONNECTION_PREFERENCE_INCLUDED);
+ }
+#endif
+ return static_cast<BssTmDataFlagsMask>(flags);
+}
+
+uint32_t getBssTmDataAssocRetryDelayMs(struct wpa_supplicant *wpa_s)
+{
+ uint32_t beacon_int;
+ uint32_t duration_ms = 0;
+
+ if (wpa_s->current_bss)
+ beacon_int = wpa_s->current_bss->beacon_int;
+ else
+ beacon_int = 100; /* best guess */
+
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
+ // number of tbtts to milliseconds
+ duration_ms = wpa_s->wnm_dissoc_timer * beacon_int * 128 / 125;
+ }
+ if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
+ //wnm_bss_termination_duration contains 12 bytes of BSS
+ //termination duration subelement. Format of IE is
+ // Sub eid | Length | BSS termination TSF | Duration
+ // 1 1 8 2
+ // Duration indicates number of minutes for which BSS is not
+ // present.
+ duration_ms = WPA_GET_LE16(wpa_s->wnm_bss_termination_duration + 10);
+ // minutes to milliseconds
+ duration_ms = duration_ms * 60 * 1000;
+ }
+#ifdef CONFIG_MBO
+ if (wpa_s->wnm_mbo_assoc_retry_delay_present) {
+ // number of seconds to milliseconds
+ duration_ms = wpa_s->wnm_mbo_assoc_retry_delay_sec * 1000;
+ }
+#endif
+
+ return duration_ms;
+}
+#endif
+
+/**
+ * Notify listener about the status of BSS transition management
+ * request frame handling.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ */
+void AidlManager::notifyBssTmStatus(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_WNM
+ std::string aidl_ifname = misc_utils::charBufToString(wpa_s->ifname);
+ BssTmData aidl_bsstm_data{};
+
+ aidl_bsstm_data.status = convertSupplicantBssTmStatusToAidl(wpa_s->bss_tm_status);
+ aidl_bsstm_data.flags = setBssTmDataFlagsMask(wpa_s);
+ aidl_bsstm_data.assocRetryDelayMs = getBssTmDataAssocRetryDelayMs(wpa_s);
+#ifdef CONFIG_MBO
+ if (wpa_s->wnm_mbo_cell_pref_present) {
+ aidl_bsstm_data.mboCellPreference = static_cast
+ <MboCellularDataConnectionPrefValue>
+ (wpa_s->wnm_mbo_cell_preference);
+ }
+ if (wpa_s->wnm_mbo_trans_reason_present) {
+ aidl_bsstm_data.mboTransitionReason =
+ static_cast<MboTransitionReasonCode>
+ (wpa_s->wnm_mbo_transition_reason);
+ }
+#endif
+
+ const std::function<
+ ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+ func = std::bind(
+ &ISupplicantStaIfaceCallback::onBssTmHandlingDone,
+ std::placeholders::_1, aidl_bsstm_data);
+ callWithEachStaIfaceCallback(aidl_ifname, func);
+#endif
+}
+
+TransitionDisableIndication setTransitionDisableFlagsMask(u8 bitmap)
+{
+ uint32_t flags = 0;
+
+ if (bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) {
+ flags |= static_cast<uint32_t>(TransitionDisableIndication::
+ USE_WPA3_PERSONAL);
+ bitmap &= ~TRANSITION_DISABLE_WPA3_PERSONAL;
+ }
+ if (bitmap & TRANSITION_DISABLE_SAE_PK) {
+ flags |= static_cast<uint32_t>(TransitionDisableIndication::
+ USE_SAE_PK);
+ bitmap &= ~TRANSITION_DISABLE_SAE_PK;
+ }
+ if (bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) {
+ flags |= static_cast<uint32_t>(TransitionDisableIndication::
+ USE_WPA3_ENTERPRISE);
+ bitmap &= ~TRANSITION_DISABLE_WPA3_ENTERPRISE;
+ }
+ if (bitmap & TRANSITION_DISABLE_ENHANCED_OPEN) {
+ flags |= static_cast<uint32_t>(TransitionDisableIndication::
+ USE_ENHANCED_OPEN);
+ bitmap &= ~TRANSITION_DISABLE_ENHANCED_OPEN;
+ }
+
+ if (bitmap != 0) {
+ wpa_printf(MSG_WARNING, "Unhandled transition disable bit: 0x%x", bitmap);
+ }
+
+ return static_cast<TransitionDisableIndication>(flags);
+}
+
+void AidlManager::notifyTransitionDisable(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid, u8 bitmap)
+{
+ TransitionDisableIndication flag = setTransitionDisableFlagsMask(bitmap);
+ const std::function<
+ ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaNetworkCallback>)>
+ func = std::bind(
+ &ISupplicantStaNetworkCallback::onTransitionDisable,
+ std::placeholders::_1, flag);
+
+ callWithEachStaNetworkCallback(
+ misc_utils::charBufToString(wpa_s->ifname), ssid->id, func);
+}
+
+void AidlManager::notifyNetworkNotFound(struct wpa_supplicant *wpa_s)
+{
+ std::vector<uint8_t> aidl_ssid;
+
+ if (!wpa_s->current_ssid) {
+ wpa_printf(MSG_ERROR, "Current network NULL. Drop WPA_EVENT_NETWORK_NOT_FOUND!");
+ return;
+ }
+
+ aidl_ssid.assign(
+ wpa_s->current_ssid->ssid,
+ wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
+
+ const std::function<
+ ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+ func = std::bind(
+ &ISupplicantStaIfaceCallback::onNetworkNotFound,
+ std::placeholders::_1, aidl_ssid);
+ callWithEachStaIfaceCallback(misc_utils::charBufToString(wpa_s->ifname), func);
+}
+
+/**
+ * Retrieve the |ISupplicantP2pIface| aidl object reference using the provided
+ * ifname.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param iface_object Aidl reference corresponding to the iface.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::getP2pIfaceAidlObjectByIfname(
+ const std::string &ifname, std::shared_ptr<ISupplicantP2pIface> *iface_object)
+{
+ if (ifname.empty() || !iface_object)
+ return 1;
+
+ auto iface_object_iter = p2p_iface_object_map_.find(ifname);
+ if (iface_object_iter == p2p_iface_object_map_.end())
+ return 1;
+
+ *iface_object = iface_object_iter->second;
+ return 0;
+}
+
+/**
+ * Retrieve the |ISupplicantStaIface| aidl object reference using the provided
+ * ifname.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param iface_object Aidl reference corresponding to the iface.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::getStaIfaceAidlObjectByIfname(
+ const std::string &ifname, std::shared_ptr<ISupplicantStaIface> *iface_object)
+{
+ if (ifname.empty() || !iface_object)
+ return 1;
+
+ auto iface_object_iter = sta_iface_object_map_.find(ifname);
+ if (iface_object_iter == sta_iface_object_map_.end())
+ return 1;
+
+ *iface_object = iface_object_iter->second;
+ return 0;
+}
+
+/**
+ * Retrieve the |ISupplicantP2pNetwork| aidl object reference using the provided
+ * ifname and network_id.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param network_object Aidl reference corresponding to the network.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::getP2pNetworkAidlObjectByIfnameAndNetworkId(
+ const std::string &ifname, int network_id,
+ std::shared_ptr<ISupplicantP2pNetwork> *network_object)
+{
+ if (ifname.empty() || network_id < 0 || !network_object)
+ return 1;
+
+ // Generate the key to be used to lookup the network.
+ const std::string network_key =
+ getNetworkObjectMapKey(ifname, network_id);
+
+ auto network_object_iter = p2p_network_object_map_.find(network_key);
+ if (network_object_iter == p2p_network_object_map_.end())
+ return 1;
+
+ *network_object = network_object_iter->second;
+ return 0;
+}
+
+/**
+ * Retrieve the |ISupplicantStaNetwork| aidl object reference using the provided
+ * ifname and network_id.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param network_object Aidl reference corresponding to the network.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::getStaNetworkAidlObjectByIfnameAndNetworkId(
+ const std::string &ifname, int network_id,
+ std::shared_ptr<ISupplicantStaNetwork> *network_object)
+{
+ if (ifname.empty() || network_id < 0 || !network_object)
+ return 1;
+
+ // Generate the key to be used to lookup the network.
+ const std::string network_key =
+ getNetworkObjectMapKey(ifname, network_id);
+
+ auto network_object_iter = sta_network_object_map_.find(network_key);
+ if (network_object_iter == sta_network_object_map_.end())
+ return 1;
+
+ *network_object = network_object_iter->second;
+ return 0;
+}
+
+/**
+ * Add a new |ISupplicantCallback| aidl object reference to our
+ * global callback list.
+ *
+ * @param callback Aidl reference of the |ISupplicantCallback| object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::addSupplicantCallbackAidlObject(
+ const std::shared_ptr<ISupplicantCallback> &callback)
+{
+ return registerForDeathAndAddCallbackAidlObjectToList<
+ ISupplicantCallback>(
+ death_notifier_, callback, supplicant_callbacks_);
+}
+
+/**
+ * Add a new iface callback aidl object reference to our
+ * interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Aidl reference of the callback object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::addP2pIfaceCallbackAidlObject(
+ const std::string &ifname,
+ const std::shared_ptr<ISupplicantP2pIfaceCallback> &callback)
+{
+ return addIfaceCallbackAidlObjectToMap(
+ death_notifier_, ifname, callback, p2p_iface_callbacks_map_);
+}
+
+/**
+ * Add a new iface callback aidl object reference to our
+ * interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Aidl reference of the callback object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::addStaIfaceCallbackAidlObject(
+ const std::string &ifname,
+ const std::shared_ptr<ISupplicantStaIfaceCallback> &callback)
+{
+ return addIfaceCallbackAidlObjectToMap(
+ death_notifier_, ifname, callback, sta_iface_callbacks_map_);
+}
+
+/**
+ * Add a new network callback aidl object reference to our network callback
+ * list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param callback Aidl reference of the callback object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int AidlManager::addStaNetworkCallbackAidlObject(
+ const std::string &ifname, int network_id,
+ const std::shared_ptr<ISupplicantStaNetworkCallback> &callback)
+{
+ return addNetworkCallbackAidlObjectToMap(
+ death_notifier_, ifname, network_id, callback,
+ sta_network_callbacks_map_);
+}
+
+/**
+ * Finds the correct |wpa_supplicant| object for P2P notifications
+ *
+ * @param wpa_s the |wpa_supplicant| that triggered the P2P event.
+ * @return appropriate |wpa_supplicant| object or NULL if not found.
+ */
+struct wpa_supplicant *AidlManager::getTargetP2pIfaceForGroup(
+ struct wpa_supplicant *wpa_group_s)
+{
+ if (!wpa_group_s || !wpa_group_s->parent)
+ return NULL;
+
+ struct wpa_supplicant *target_wpa_s = wpa_group_s->parent;
+
+ // check wpa_supplicant object is a p2p device interface
+ if ((wpa_group_s == wpa_group_s->p2pdev) && wpa_group_s->p2p_mgmt) {
+ if (p2p_iface_object_map_.find(wpa_group_s->ifname) !=
+ p2p_iface_object_map_.end())
+ return wpa_group_s;
+ }
+
+ if (p2p_iface_object_map_.find(target_wpa_s->ifname) !=
+ p2p_iface_object_map_.end())
+ return target_wpa_s;
+
+ // try P2P device if available
+ if (!target_wpa_s->p2pdev || !target_wpa_s->p2pdev->p2p_mgmt)
+ return NULL;
+
+ target_wpa_s = target_wpa_s->p2pdev;
+ if (p2p_iface_object_map_.find(target_wpa_s->ifname) !=
+ p2p_iface_object_map_.end())
+ return target_wpa_s;
+
+ return NULL;
+}
+
+/**
+ * Removes the provided |ISupplicantCallback| aidl object reference
+ * from our global callback list.
+ *
+ * @param callback Aidl reference of the |ISupplicantCallback| object.
+ */
+void AidlManager::removeSupplicantCallbackAidlObject(
+ const std::shared_ptr<ISupplicantCallback> &callback)
+{
+ supplicant_callbacks_.erase(
+ std::remove(
+ supplicant_callbacks_.begin(), supplicant_callbacks_.end(),
+ callback),
+ supplicant_callbacks_.end());
+}
+
+/**
+ * Removes the provided iface callback aidl object reference from
+ * our interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Aidl reference of the callback object.
+ */
+void AidlManager::removeP2pIfaceCallbackAidlObject(
+ const std::string &ifname,
+ const std::shared_ptr<ISupplicantP2pIfaceCallback> &callback)
+{
+ return removeIfaceCallbackAidlObjectFromMap(
+ ifname, callback, p2p_iface_callbacks_map_);
+}
+
+/**
+ * Removes the provided iface callback aidl object reference from
+ * our interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Aidl reference of the callback object.
+ */
+void AidlManager::removeStaIfaceCallbackAidlObject(
+ const std::string &ifname,
+ const std::shared_ptr<ISupplicantStaIfaceCallback> &callback)
+{
+ return removeIfaceCallbackAidlObjectFromMap(
+ ifname, callback, sta_iface_callbacks_map_);
+}
+
+/**
+ * Removes the provided network callback aidl object reference from
+ * our network callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param callback Aidl reference of the callback object.
+ */
+void AidlManager::removeStaNetworkCallbackAidlObject(
+ const std::string &ifname, int network_id,
+ const std::shared_ptr<ISupplicantStaNetworkCallback> &callback)
+{
+ return removeNetworkCallbackAidlObjectFromMap(
+ ifname, network_id, callback, sta_network_callbacks_map_);
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered |ISupplicantCallback| callback aidl objects.
+ *
+ * @param method Pointer to the required aidl method from
+ * |ISupplicantCallback|.
+ */
+void AidlManager::callWithEachSupplicantCallback(
+ const std::function<ndk::ScopedAStatus(std::shared_ptr<ISupplicantCallback>)> &method)
+{
+ for (const auto &callback : supplicant_callbacks_) {
+ if (!method(callback).isOk()) {
+ wpa_printf(MSG_ERROR, "Failed to invoke AIDL callback");
+ }
+ }
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered iface callback aidl objects for the specified
+ * |ifname|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param method Pointer to the required aidl method from
+ * |ISupplicantIfaceCallback|.
+ */
+void AidlManager::callWithEachP2pIfaceCallback(
+ const std::string &ifname,
+ const std::function<ndk::ScopedAStatus(std::shared_ptr<ISupplicantP2pIfaceCallback>)>
+ &method)
+{
+ callWithEachIfaceCallback(ifname, method, p2p_iface_callbacks_map_);
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered interface callback aidl objects for the specified
+ * |ifname|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param method Pointer to the required aidl method from
+ * |ISupplicantIfaceCallback|.
+ */
+void AidlManager::callWithEachStaIfaceCallback(
+ const std::string &ifname,
+ const std::function<ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaIfaceCallback>)>
+ &method)
+{
+ callWithEachIfaceCallback(ifname, method, sta_iface_callbacks_map_);
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered network callback aidl objects for the specified
+ * |ifname| & |network_id|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param method Pointer to the required aidl method from
+ * |ISupplicantStaNetworkCallback|.
+ */
+void AidlManager::callWithEachStaNetworkCallback(
+ const std::string &ifname, int network_id,
+ const std::function<
+ ndk::ScopedAStatus(std::shared_ptr<ISupplicantStaNetworkCallback>)> &method)
+{
+ callWithEachNetworkCallback(
+ ifname, network_id, method, sta_network_callbacks_map_);
+}
+
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wpa_supplicant/aidl/aidl_manager.h b/wpa_supplicant/aidl/aidl_manager.h
new file mode 100644
index 0000000..b538e36
--- /dev/null
+++ b/wpa_supplicant/aidl/aidl_manager.h
@@ -0,0 +1,701 @@
+/*
+ * WPA Supplicant - Manager for Aidl interface objects
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_AIDL_MANAGER_H
+#define WPA_SUPPLICANT_AIDL_AIDL_MANAGER_H
+
+#include <map>
+#include <string>
+
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.h>
+
+#include "p2p_iface.h"
+#include "p2p_network.h"
+#include "rsn_supp/pmksa_cache.h"
+#include "sta_iface.h"
+#include "sta_network.h"
+#include "supplicant.h"
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+/**
+ * AidlManager is responsible for managing the lifetime of all
+ * aidl objects created by wpa_supplicant. This is a singleton
+ * class which is created by the supplicant core and can be used
+ * to get references to the aidl objects.
+ */
+class AidlManager
+{
+public:
+ static AidlManager *getInstance();
+ static void destroyInstance();
+
+ // Methods called from wpa_supplicant core.
+ int registerAidlService(struct wpa_global *global);
+ int registerInterface(struct wpa_supplicant *wpa_s);
+ int unregisterInterface(struct wpa_supplicant *wpa_s);
+ int registerNetwork(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+ int unregisterNetwork(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+ int notifyStateChange(struct wpa_supplicant *wpa_s);
+ int notifyNetworkRequest(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int type,
+ const char *param);
+ void notifyAnqpQueryDone(
+ struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+ const struct wpa_bss_anqp *anqp);
+ void notifyHs20IconQueryDone(
+ struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const char *file_name, const u8 *image, u32 image_length);
+ void notifyHs20RxSubscriptionRemediation(
+ struct wpa_supplicant *wpa_s, const char *url, u8 osu_method);
+ void notifyHs20RxDeauthImminentNotice(
+ struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay,
+ const char *url);
+ void notifyHs20RxTermsAndConditionsAcceptance(
+ struct wpa_supplicant *wpa_s, const char *url);
+ void notifyDisconnectReason(struct wpa_supplicant *wpa_s);
+ void notifyAssocReject(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ u8 timed_out, const u8 *assoc_resp_ie, size_t assoc_resp_ie_len);
+ void notifyAuthTimeout(struct wpa_supplicant *wpa_s);
+ void notifyBssidChanged(struct wpa_supplicant *wpa_s);
+ void notifyWpsEventFail(
+ struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr,
+ uint16_t config_error, uint16_t error_indication);
+ void notifyWpsEventSuccess(struct wpa_supplicant *wpa_s);
+ void notifyWpsEventPbcOverlap(struct wpa_supplicant *wpa_s);
+ void notifyP2pDeviceFound(
+ struct wpa_supplicant *wpa_s, const u8 *addr,
+ const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+ u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+ u8 peer_wfd_r2_device_info_len);
+ void notifyP2pDeviceLost(
+ struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr);
+ void notifyP2pFindStopped(struct wpa_supplicant *wpa_s);
+ void notifyP2pGoNegReq(
+ struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+ u8 go_intent);
+ void notifyP2pGoNegCompleted(
+ struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res);
+ void notifyP2pGroupFormationFailure(
+ struct wpa_supplicant *wpa_s, const char *reason);
+ void notifyP2pGroupStarted(
+ struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
+ int persistent, int client);
+ void notifyP2pGroupRemoved(
+ struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
+ const char *role);
+ void notifyP2pInvitationReceived(
+ struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+ const u8 *bssid, int id, int op_freq);
+ void notifyP2pInvitationResult(
+ struct wpa_supplicant *wpa_s, int status, const u8 *bssid);
+ void notifyP2pProvisionDiscovery(
+ struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+ enum p2p_prov_disc_status status, u16 config_methods,
+ unsigned int generated_pin);
+ void notifyP2pSdResponse(
+ struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+ const u8 *tlvs, size_t tlvs_len);
+ void notifyApStaAuthorized(
+ struct wpa_supplicant *wpa_s, const u8 *sta,
+ const u8 *p2p_dev_addr);
+ void notifyApStaDeauthorized(
+ struct wpa_supplicant *wpa_s, const u8 *sta,
+ const u8 *p2p_dev_addr);
+ void notifyEapError(struct wpa_supplicant *wpa_s, int error_code);
+ void notifyDppConfigReceived(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *config);
+ void notifyDppConfigSent(struct wpa_supplicant *wpa_s);
+ void notifyDppSuccess(struct wpa_supplicant *wpa_s, DppEventType code);
+ void notifyDppFailure(struct wpa_supplicant *wpa_s,
+ DppFailureCode code);
+ void notifyDppFailure(struct wpa_supplicant *wpa_s,
+ DppFailureCode code,
+ const char *ssid, const char *channel_list, unsigned short band_list[],
+ int size);
+ void notifyDppProgress(struct wpa_supplicant *wpa_s,
+ DppProgressCode code);
+ void notifyPmkCacheAdded(struct wpa_supplicant *wpa_s,
+ struct rsn_pmksa_cache_entry *pmksa_entry);
+ void notifyBssTmStatus(struct wpa_supplicant *wpa_s);
+ void notifyTransitionDisable(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ u8 bitmap);
+ void notifyNetworkNotFound(struct wpa_supplicant *wpa_s);
+
+ // Methods called from aidl objects.
+ void notifyExtRadioWorkStart(struct wpa_supplicant *wpa_s, uint32_t id);
+ void notifyExtRadioWorkTimeout(
+ struct wpa_supplicant *wpa_s, uint32_t id);
+
+ int getP2pIfaceAidlObjectByIfname(
+ const std::string &ifname,
+ std::shared_ptr<ISupplicantP2pIface> *iface_object);
+ int getStaIfaceAidlObjectByIfname(
+ const std::string &ifname,
+ std::shared_ptr<ISupplicantStaIface> *iface_object);
+ int getP2pNetworkAidlObjectByIfnameAndNetworkId(
+ const std::string &ifname, int network_id,
+ std::shared_ptr<ISupplicantP2pNetwork> *network_object);
+ int getStaNetworkAidlObjectByIfnameAndNetworkId(
+ const std::string &ifname, int network_id,
+ std::shared_ptr<ISupplicantStaNetwork> *network_object);
+ int addSupplicantCallbackAidlObject(
+ const std::shared_ptr<ISupplicantCallback> &callback);
+ int addP2pIfaceCallbackAidlObject(
+ const std::string &ifname,
+ const std::shared_ptr<ISupplicantP2pIfaceCallback> &callback);
+ int addStaIfaceCallbackAidlObject(
+ const std::string &ifname,
+ const std::shared_ptr<ISupplicantStaIfaceCallback> &callback);
+ int addStaNetworkCallbackAidlObject(
+ const std::string &ifname, int network_id,
+ const std::shared_ptr<ISupplicantStaNetworkCallback> &callback);
+
+private:
+ AidlManager() = default;
+ ~AidlManager() = default;
+ AidlManager(const AidlManager &) = default;
+ AidlManager &operator=(const AidlManager &) = default;
+
+ struct wpa_supplicant *getTargetP2pIfaceForGroup(
+ struct wpa_supplicant *wpa_s);
+ void removeSupplicantCallbackAidlObject(
+ const std::shared_ptr<ISupplicantCallback> &callback);
+ void removeP2pIfaceCallbackAidlObject(
+ const std::string &ifname,
+ const std::shared_ptr<ISupplicantP2pIfaceCallback> &callback);
+ void removeStaIfaceCallbackAidlObject(
+ const std::string &ifname,
+ const std::shared_ptr<ISupplicantStaIfaceCallback> &callback);
+ void removeStaNetworkCallbackAidlObject(
+ const std::string &ifname, int network_id,
+ const std::shared_ptr<ISupplicantStaNetworkCallback> &callback);
+
+ void callWithEachSupplicantCallback(
+ const std::function<ndk::ScopedAStatus(
+ std::shared_ptr<ISupplicantCallback>)> &method);
+ void callWithEachP2pIfaceCallback(
+ const std::string &ifname,
+ const std::function<ndk::ScopedAStatus(
+ std::shared_ptr<ISupplicantP2pIfaceCallback>)> &method);
+ void callWithEachStaIfaceCallback(
+ const std::string &ifname,
+ const std::function<ndk::ScopedAStatus(
+ std::shared_ptr<ISupplicantStaIfaceCallback>)> &method);
+ void callWithEachStaNetworkCallback(
+ const std::string &ifname, int network_id,
+ const std::function<::ndk::ScopedAStatus(
+ std::shared_ptr<ISupplicantStaNetworkCallback>)> &method);
+
+ // Singleton instance of this class.
+ static AidlManager *instance_;
+ // Death notifier.
+ AIBinder_DeathRecipient* death_notifier_;
+ // The main aidl service object.
+ std::shared_ptr<Supplicant> supplicant_object_;
+ // Map of all the P2P interface specific aidl objects controlled by
+ // wpa_supplicant. This map is keyed in by the corresponding
+ // |ifname|.
+ std::map<const std::string, std::shared_ptr<P2pIface>>
+ p2p_iface_object_map_;
+ // Map of all the STA interface specific aidl objects controlled by
+ // wpa_supplicant. This map is keyed in by the corresponding
+ // |ifname|.
+ std::map<const std::string, std::shared_ptr<StaIface>>
+ sta_iface_object_map_;
+ // Map of all the P2P network specific aidl objects controlled by
+ // wpa_supplicant. This map is keyed in by the corresponding
+ // |ifname| & |network_id|.
+ std::map<const std::string, std::shared_ptr<P2pNetwork>>
+ p2p_network_object_map_;
+ // Map of all the STA network specific aidl objects controlled by
+ // wpa_supplicant. This map is keyed in by the corresponding
+ // |ifname| & |network_id|.
+ std::map<const std::string, std::shared_ptr<StaNetwork>>
+ sta_network_object_map_;
+
+ // Callbacks registered for the main aidl service object.
+ std::vector<std::shared_ptr<ISupplicantCallback>> supplicant_callbacks_;
+ // Map of all the callbacks registered for P2P interface specific
+ // aidl objects controlled by wpa_supplicant. This map is keyed in by
+ // the corresponding |ifname|.
+ std::map<
+ const std::string,
+ std::vector<std::shared_ptr<ISupplicantP2pIfaceCallback>>>
+ p2p_iface_callbacks_map_;
+ // Map of all the callbacks registered for STA interface specific
+ // aidl objects controlled by wpa_supplicant. This map is keyed in by
+ // the corresponding |ifname|.
+ std::map<
+ const std::string,
+ std::vector<std::shared_ptr<ISupplicantStaIfaceCallback>>>
+ sta_iface_callbacks_map_;
+ // Map of all the callbacks registered for STA network specific
+ // aidl objects controlled by wpa_supplicant. This map is keyed in by
+ // the corresponding |ifname| & |network_id|.
+ std::map<
+ const std::string,
+ std::vector<std::shared_ptr<ISupplicantStaNetworkCallback>>>
+ sta_network_callbacks_map_;
+};
+
+// The aidl interface uses some values which are the same as internal ones to
+// avoid nasty runtime conversion functions. So, adding compile time asserts
+// to guard against any internal changes breaking the aidl interface.
+static_assert(
+ static_cast<uint32_t>(DebugLevel::EXCESSIVE) == MSG_EXCESSIVE,
+ "Debug level value mismatch");
+static_assert(
+ static_cast<uint32_t>(DebugLevel::ERROR) == MSG_ERROR,
+ "Debug level value mismatch");
+
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::NONE) ==
+ WPA_KEY_MGMT_NONE,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::WPA_PSK) ==
+ WPA_KEY_MGMT_PSK,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::WPA_EAP) ==
+ WPA_KEY_MGMT_IEEE8021X,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::IEEE8021X) ==
+ WPA_KEY_MGMT_IEEE8021X_NO_WPA,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::FT_EAP) ==
+ WPA_KEY_MGMT_FT_IEEE8021X,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::FT_PSK) ==
+ WPA_KEY_MGMT_FT_PSK,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::OSEN) ==
+ WPA_KEY_MGMT_OSEN,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::SAE) ==
+ WPA_KEY_MGMT_SAE,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::SUITE_B_192) ==
+ WPA_KEY_MGMT_IEEE8021X_SUITE_B_192,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::OWE) ==
+ WPA_KEY_MGMT_OWE,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::WPA_PSK_SHA256) ==
+ WPA_KEY_MGMT_PSK_SHA256,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::WPA_EAP_SHA256) ==
+ WPA_KEY_MGMT_IEEE8021X_SHA256,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::WAPI_PSK) ==
+ WPA_KEY_MGMT_WAPI_PSK,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(KeyMgmtMask::WAPI_CERT) ==
+ WPA_KEY_MGMT_WAPI_CERT,
+ "KeyMgmt value mismatch");
+static_assert(
+ static_cast<uint32_t>(ProtoMask::WPA) ==
+ WPA_PROTO_WPA,
+ "Proto value mismatch");
+static_assert(
+ static_cast<uint32_t>(ProtoMask::RSN) ==
+ WPA_PROTO_RSN,
+ "Proto value mismatch");
+static_assert(
+ static_cast<uint32_t>(ProtoMask::OSEN) ==
+ WPA_PROTO_OSEN,
+ "Proto value mismatch");
+static_assert(
+ static_cast<uint32_t>(ProtoMask::WAPI) ==
+ WPA_PROTO_WAPI,
+ "Proto value mismatch");
+static_assert(
+ static_cast<uint32_t>(AuthAlgMask::OPEN) ==
+ WPA_AUTH_ALG_OPEN,
+ "AuthAlg value mismatch");
+static_assert(
+ static_cast<uint32_t>(AuthAlgMask::SHARED) ==
+ WPA_AUTH_ALG_SHARED,
+ "AuthAlg value mismatch");
+static_assert(
+ static_cast<uint32_t>(AuthAlgMask::LEAP) ==
+ WPA_AUTH_ALG_LEAP,
+ "AuthAlg value mismatch");
+static_assert(
+ static_cast<uint32_t>(GroupCipherMask::WEP40) ==
+ WPA_CIPHER_WEP40,
+ "GroupCipher value mismatch");
+static_assert(
+ static_cast<uint32_t>(GroupCipherMask::WEP104) ==
+ WPA_CIPHER_WEP104,
+ "GroupCipher value mismatch");
+static_assert(
+ static_cast<uint32_t>(GroupCipherMask::TKIP) ==
+ WPA_CIPHER_TKIP,
+ "GroupCipher value mismatch");
+static_assert(
+ static_cast<uint32_t>(GroupCipherMask::CCMP) ==
+ WPA_CIPHER_CCMP,
+ "GroupCipher value mismatch");
+static_assert(
+ static_cast<uint32_t>(GroupCipherMask::GCMP_256) ==
+ WPA_CIPHER_GCMP_256,
+ "GroupCipher value mismatch");
+static_assert(
+ static_cast<uint32_t>(GroupCipherMask::SMS4) ==
+ WPA_CIPHER_SMS4,
+ "GroupCipher value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ GroupCipherMask::GTK_NOT_USED) ==
+ WPA_CIPHER_GTK_NOT_USED,
+ "GroupCipher value mismatch");
+static_assert(
+ static_cast<uint32_t>(PairwiseCipherMask::NONE) ==
+ WPA_CIPHER_NONE,
+ "PairwiseCipher value mismatch");
+static_assert(
+ static_cast<uint32_t>(PairwiseCipherMask::TKIP) ==
+ WPA_CIPHER_TKIP,
+ "PairwiseCipher value mismatch");
+static_assert(
+ static_cast<uint32_t>(PairwiseCipherMask::CCMP) ==
+ WPA_CIPHER_CCMP,
+ "PairwiseCipher value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ PairwiseCipherMask::GCMP_256) ==
+ WPA_CIPHER_GCMP_256,
+ "PairwiseCipher value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ PairwiseCipherMask::SMS4) ==
+ WPA_CIPHER_SMS4,
+ "PairwiseCipher value mismatch");
+static_assert(
+ static_cast<uint32_t>(StaIfaceCallbackState::DISCONNECTED) ==
+ WPA_DISCONNECTED,
+ "State value mismatch");
+static_assert(
+ static_cast<uint32_t>(StaIfaceCallbackState::COMPLETED) ==
+ WPA_COMPLETED,
+ "State value mismatch");
+
+static_assert(
+ static_cast<uint32_t>(AnqpInfoId::VENUE_NAME) ==
+ ANQP_VENUE_NAME,
+ "ANQP ID value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ AnqpInfoId::ROAMING_CONSORTIUM) ==
+ ANQP_ROAMING_CONSORTIUM,
+ "ANQP ID value mismatch");
+static_assert(
+ static_cast<uint32_t>(AnqpInfoId::NAI_REALM) ==
+ ANQP_NAI_REALM,
+ "ANQP ID value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ AnqpInfoId::IP_ADDR_TYPE_AVAILABILITY) ==
+ ANQP_IP_ADDR_TYPE_AVAILABILITY,
+ "ANQP ID value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ AnqpInfoId::ANQP_3GPP_CELLULAR_NETWORK) ==
+ ANQP_3GPP_CELLULAR_NETWORK,
+ "ANQP ID value mismatch");
+static_assert(
+ static_cast<uint32_t>(AnqpInfoId::DOMAIN_NAME) ==
+ ANQP_DOMAIN_NAME,
+ "ANQP ID value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ Hs20AnqpSubtypes::OPERATOR_FRIENDLY_NAME) ==
+ HS20_STYPE_OPERATOR_FRIENDLY_NAME,
+ "HS Subtype value mismatch");
+static_assert(
+ static_cast<uint32_t>(Hs20AnqpSubtypes::WAN_METRICS) ==
+ HS20_STYPE_WAN_METRICS,
+ "HS Subtype value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ Hs20AnqpSubtypes::CONNECTION_CAPABILITY) ==
+ HS20_STYPE_CONNECTION_CAPABILITY,
+ "HS Subtype value mismatch");
+static_assert(
+ static_cast<uint32_t>(
+ Hs20AnqpSubtypes::OSU_PROVIDERS_LIST) ==
+ HS20_STYPE_OSU_PROVIDERS_LIST,
+ "HS Subtype value mismatch");
+
+static_assert(
+ static_cast<uint16_t>(
+ WpsConfigError::NO_ERROR) ==
+ WPS_CFG_NO_ERROR,
+ "Wps config error value mismatch");
+static_assert(
+ static_cast<uint16_t>(WpsConfigError::
+ PUBLIC_KEY_HASH_MISMATCH) ==
+ WPS_CFG_PUBLIC_KEY_HASH_MISMATCH,
+ "Wps config error value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ WpsErrorIndication::NO_ERROR) ==
+ WPS_EI_NO_ERROR,
+ "Wps error indication value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ WpsErrorIndication::AUTH_FAILURE) ==
+ WPS_EI_AUTH_FAILURE,
+ "Wps error indication value mismatch");
+
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::USBA) == WPS_CONFIG_USBA,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::ETHERNET) == WPS_CONFIG_ETHERNET,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::LABEL) == WPS_CONFIG_LABEL,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::DISPLAY) == WPS_CONFIG_DISPLAY,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::INT_NFC_TOKEN) ==
+ WPS_CONFIG_INT_NFC_TOKEN,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::EXT_NFC_TOKEN) ==
+ WPS_CONFIG_EXT_NFC_TOKEN,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::NFC_INTERFACE) ==
+ WPS_CONFIG_NFC_INTERFACE,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::PUSHBUTTON) ==
+ WPS_CONFIG_PUSHBUTTON,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::KEYPAD) == WPS_CONFIG_KEYPAD,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::VIRT_PUSHBUTTON) ==
+ WPS_CONFIG_VIRT_PUSHBUTTON,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::PHY_PUSHBUTTON) ==
+ WPS_CONFIG_PHY_PUSHBUTTON,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::P2PS) == WPS_CONFIG_P2PS,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::VIRT_DISPLAY) ==
+ WPS_CONFIG_VIRT_DISPLAY,
+ "Wps config value mismatch");
+static_assert(
+ static_cast<uint32_t>(WpsConfigMethods::PHY_DISPLAY) ==
+ WPS_CONFIG_PHY_DISPLAY,
+ "Wps config value mismatch");
+
+static_assert(
+ static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_OWNER) ==
+ P2P_GROUP_CAPAB_GROUP_OWNER,
+ "P2P capability value mismatch");
+static_assert(
+ static_cast<uint32_t>(P2pGroupCapabilityMask::PERSISTENT_GROUP) ==
+ P2P_GROUP_CAPAB_PERSISTENT_GROUP,
+ "P2P capability value mismatch");
+static_assert(
+ static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_LIMIT) ==
+ P2P_GROUP_CAPAB_GROUP_LIMIT,
+ "P2P capability value mismatch");
+static_assert(
+ static_cast<uint32_t>(P2pGroupCapabilityMask::INTRA_BSS_DIST) ==
+ P2P_GROUP_CAPAB_INTRA_BSS_DIST,
+ "P2P capability value mismatch");
+static_assert(
+ static_cast<uint32_t>(P2pGroupCapabilityMask::CROSS_CONN) ==
+ P2P_GROUP_CAPAB_CROSS_CONN,
+ "P2P capability value mismatch");
+static_assert(
+ static_cast<uint32_t>(P2pGroupCapabilityMask::PERSISTENT_RECONN) ==
+ P2P_GROUP_CAPAB_PERSISTENT_RECONN,
+ "P2P capability value mismatch");
+static_assert(
+ static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_FORMATION) ==
+ P2P_GROUP_CAPAB_GROUP_FORMATION,
+ "P2P capability value mismatch");
+
+static_assert(
+ static_cast<uint16_t>(
+ WpsDevPasswordId::DEFAULT) ==
+ DEV_PW_DEFAULT,
+ "Wps dev password id value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ WpsDevPasswordId::USER_SPECIFIED) ==
+ DEV_PW_USER_SPECIFIED,
+ "Wps dev password id value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ WpsDevPasswordId::MACHINE_SPECIFIED) ==
+ DEV_PW_MACHINE_SPECIFIED,
+ "Wps dev password id value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ WpsDevPasswordId::REKEY) == DEV_PW_REKEY,
+ "Wps dev password id value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ WpsDevPasswordId::PUSHBUTTON) ==
+ DEV_PW_PUSHBUTTON,
+ "Wps dev password id value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ WpsDevPasswordId::REGISTRAR_SPECIFIED) ==
+ DEV_PW_REGISTRAR_SPECIFIED,
+ "Wps dev password id value mismatch");
+static_assert(
+ static_cast<uint16_t>(WpsDevPasswordId::
+ NFC_CONNECTION_HANDOVER) ==
+ DEV_PW_NFC_CONNECTION_HANDOVER,
+ "Wps dev password id value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ WpsDevPasswordId::P2PS_DEFAULT) ==
+ DEV_PW_P2PS_DEFAULT,
+ "Wps dev password id value mismatch");
+
+static_assert(
+ static_cast<uint16_t>(
+ P2pStatusCode::SUCCESS) == P2P_SC_SUCCESS,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(P2pStatusCode::
+ FAIL_INFO_CURRENTLY_UNAVAILABLE) ==
+ P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pStatusCode::FAIL_INCOMPATIBLE_PARAMS) ==
+ P2P_SC_FAIL_INCOMPATIBLE_PARAMS,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pStatusCode::FAIL_LIMIT_REACHED) ==
+ P2P_SC_FAIL_LIMIT_REACHED,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pStatusCode::FAIL_INVALID_PARAMS) ==
+ P2P_SC_FAIL_INVALID_PARAMS,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(P2pStatusCode::
+ FAIL_UNABLE_TO_ACCOMMODATE) ==
+ P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pStatusCode::FAIL_PREV_PROTOCOL_ERROR) ==
+ P2P_SC_FAIL_PREV_PROTOCOL_ERROR,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pStatusCode::FAIL_NO_COMMON_CHANNELS) ==
+ P2P_SC_FAIL_NO_COMMON_CHANNELS,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pStatusCode::FAIL_UNKNOWN_GROUP) ==
+ P2P_SC_FAIL_UNKNOWN_GROUP,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pStatusCode::FAIL_BOTH_GO_INTENT_15) ==
+ P2P_SC_FAIL_BOTH_GO_INTENT_15,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(P2pStatusCode::
+ FAIL_INCOMPATIBLE_PROV_METHOD) ==
+ P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pStatusCode::FAIL_REJECTED_BY_USER) ==
+ P2P_SC_FAIL_REJECTED_BY_USER,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pStatusCode::SUCCESS_DEFERRED) ==
+ P2P_SC_SUCCESS_DEFERRED,
+ "P2P status code value mismatch");
+
+static_assert(
+ static_cast<uint16_t>(
+ P2pProvDiscStatusCode::SUCCESS) ==
+ P2P_PROV_DISC_SUCCESS,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pProvDiscStatusCode::TIMEOUT) ==
+ P2P_PROV_DISC_TIMEOUT,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pProvDiscStatusCode::REJECTED) ==
+ P2P_PROV_DISC_REJECTED,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pProvDiscStatusCode::TIMEOUT_JOIN) ==
+ P2P_PROV_DISC_TIMEOUT_JOIN,
+ "P2P status code value mismatch");
+static_assert(
+ static_cast<uint16_t>(
+ P2pProvDiscStatusCode::INFO_UNAVAILABLE) ==
+ P2P_PROV_DISC_INFO_UNAVAILABLE,
+ "P2P status code value mismatch");
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+#endif // WPA_SUPPLICANT_AIDL_AIDL_MANAGER_H
diff --git a/wpa_supplicant/aidl/aidl_return_util.h b/wpa_supplicant/aidl/aidl_return_util.h
new file mode 100644
index 0000000..109723a
--- /dev/null
+++ b/wpa_supplicant/aidl/aidl_return_util.h
@@ -0,0 +1,66 @@
+/*
+ * WPA Supplicant - Validate interfaces before calling methods
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef AIDL_RETURN_UTIL_H_
+#define AIDL_RETURN_UTIL_H_
+
+#include <aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace aidl_return_util {
+
+/**
+ * These utility functions are used to invoke a method on the provided
+ * AIDL interface object.
+ * These functions check if the provided AIDL interface object is valid.
+ * a) If valid, invokes the corresponding internal implementation function of
+ * the AIDL method.
+ * b) If invalid, return without calling the internal implementation function.
+ */
+
+// Use for AIDL methods which only return an AIDL status
+template <typename ObjT, typename WorkFuncT, typename... Args>
+::ndk::ScopedAStatus validateAndCall(
+ ObjT* obj, SupplicantStatusCode status_code_if_invalid, WorkFuncT&& work,
+ Args&&... args)
+{
+ if (obj->isValid()) {
+ return (obj->*work)(std::forward<Args>(args)...);
+ } else {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(status_code_if_invalid));
+ }
+}
+
+// Use for AIDL methods which have a return value along with the AIDL status
+template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
+::ndk::ScopedAStatus validateAndCall(
+ ObjT* obj, SupplicantStatusCode status_code_if_invalid, WorkFuncT&& work,
+ ReturnT* ret_val, Args&&... args)
+{
+ if (obj->isValid()) {
+ auto call_pair = (obj->*work)(std::forward<Args>(args)...);
+ *ret_val = call_pair.first;
+ return std::forward<::ndk::ScopedAStatus>(call_pair.second);
+ } else {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(status_code_if_invalid));
+ }
+}
+
+} // namespace aidl_return_util
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+#endif // AIDL_RETURN_UTIL_H_
diff --git a/wpa_supplicant/aidl/android.hardware.wifi.supplicant-service.rc b/wpa_supplicant/aidl/android.hardware.wifi.supplicant-service.rc
new file mode 100644
index 0000000..3275e36
--- /dev/null
+++ b/wpa_supplicant/aidl/android.hardware.wifi.supplicant-service.rc
@@ -0,0 +1,12 @@
+service wpa_supplicant /vendor/bin/hw/wpa_supplicant \
+ -O/data/vendor/wifi/wpa/sockets -dd \
+ -g@android:wpa_wlan0
+ # we will start as root and wpa_supplicant will switch to user wifi
+ # after setting up the capabilities required for WEXT
+ # user wifi
+ # group wifi inet keystore
+ interface aidl android.hardware.wifi.supplicant.ISupplicant/default
+ class main
+ socket wpa_wlan0 dgram 660 wifi wifi
+ disabled
+ oneshot
diff --git a/wpa_supplicant/aidl/android.hardware.wifi.supplicant.xml b/wpa_supplicant/aidl/android.hardware.wifi.supplicant.xml
new file mode 100644
index 0000000..3dc9b02
--- /dev/null
+++ b/wpa_supplicant/aidl/android.hardware.wifi.supplicant.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.wifi.supplicant</name>
+ <fqname>ISupplicant/default</fqname>
+ </hal>
+</manifest>
diff --git a/wpa_supplicant/aidl/iface_config_utils.cpp b/wpa_supplicant/aidl/iface_config_utils.cpp
new file mode 100644
index 0000000..4d3f29c
--- /dev/null
+++ b/wpa_supplicant/aidl/iface_config_utils.cpp
@@ -0,0 +1,179 @@
+/*
+ * WPA Supplicant - Iface configuration methods
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "aidl_manager.h"
+#include "aidl_return_util.h"
+#include "iface_config_utils.h"
+#include "misc_utils.h"
+
+namespace {
+using aidl::android::hardware::wifi::supplicant::SupplicantStatusCode;
+using aidl::android::hardware::wifi::supplicant::WpsConfigMethods;
+
+constexpr uint32_t kMaxWpsDeviceNameSize = WPS_DEV_NAME_MAX_LEN;
+constexpr uint32_t kMaxWpsManufacturerSize = WPS_MANUFACTURER_MAX_LEN;
+constexpr uint32_t kMaxWpsModelNameSize = WPS_MODEL_NAME_MAX_LEN;
+constexpr uint32_t kMaxWpsModelNumberSize = WPS_MODEL_NUMBER_MAX_LEN;
+constexpr uint32_t kMaxWpsSerialNumberSize = WPS_SERIAL_NUMBER_MAX_LEN;
+
+void processConfigUpdate(struct wpa_supplicant* wpa_s, uint32_t changed_param)
+{
+ wpa_s->conf->changed_parameters |= changed_param;
+ wpa_supplicant_update_config(wpa_s);
+}
+
+// Free any existing pointer stored in |dst| and store the provided string value
+// there.
+int freeAndSetStringConfigParam(
+ struct wpa_supplicant* wpa_s, const std::string& value, uint32_t max_size,
+ uint32_t changed_param, char** dst)
+{
+ if (value.size() > max_size) {
+ return -1;
+ }
+ WPA_ASSERT(dst);
+ os_free(static_cast<void*>(*dst));
+ *dst = os_strdup(value.c_str());
+ processConfigUpdate(wpa_s, changed_param);
+ return 0;
+}
+
+std::string convertWpsConfigMethodsMaskToString(uint16_t config_methods)
+{
+ std::string config_methods_str;
+ for (const auto& flag_and_name :
+ {std::make_pair(WpsConfigMethods::USBA, "usba"),
+ {WpsConfigMethods::ETHERNET, "ethernet"},
+ {WpsConfigMethods::LABEL, "label"},
+ {WpsConfigMethods::DISPLAY, "display"},
+ {WpsConfigMethods::INT_NFC_TOKEN, "int_nfc_token"},
+ {WpsConfigMethods::EXT_NFC_TOKEN, "ext_nfc_token"},
+ {WpsConfigMethods::NFC_INTERFACE, "nfc_interface"},
+ {WpsConfigMethods::PUSHBUTTON, "push_button"},
+ {WpsConfigMethods::KEYPAD, "keypad"},
+ {WpsConfigMethods::VIRT_PUSHBUTTON, "virtual_push_button"},
+ {WpsConfigMethods::PHY_PUSHBUTTON, "physical_push_button"},
+ {WpsConfigMethods::P2PS, "p2ps"},
+ {WpsConfigMethods::VIRT_DISPLAY, "virtual_display"},
+ {WpsConfigMethods::PHY_DISPLAY, "physical_display"}}) {
+ const auto flag =
+ static_cast<std::underlying_type<WpsConfigMethods>::type>(
+ flag_and_name.first);
+ if ((config_methods & flag) == flag) {
+ config_methods_str += flag_and_name.second;
+ config_methods_str += " ";
+ }
+ }
+ return config_methods_str;
+}
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace iface_config_utils {
+using misc_utils::createStatus;
+
+ndk::ScopedAStatus setWpsDeviceName(
+ struct wpa_supplicant* wpa_s, const std::string& name)
+{
+ WPA_ASSERT(wpa_s);
+ if (freeAndSetStringConfigParam(
+ wpa_s, name, kMaxWpsDeviceNameSize, CFG_CHANGED_DEVICE_NAME,
+ &wpa_s->conf->device_name)) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setWpsDeviceType(
+ struct wpa_supplicant* wpa_s, const std::array<uint8_t, WPS_DEV_TYPE_LEN>& type)
+{
+ WPA_ASSERT(wpa_s);
+ WPA_ASSERT(type.size() == WPS_DEV_TYPE_LEN);
+ os_memcpy(wpa_s->conf->device_type, type.data(), WPS_DEV_TYPE_LEN);
+ processConfigUpdate(wpa_s, CFG_CHANGED_DEVICE_TYPE);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setWpsManufacturer(
+ struct wpa_supplicant* wpa_s, const std::string& manufacturer)
+{
+ WPA_ASSERT(wpa_s);
+ if (freeAndSetStringConfigParam(
+ wpa_s, manufacturer, kMaxWpsManufacturerSize,
+ CFG_CHANGED_WPS_STRING, &wpa_s->conf->manufacturer)) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setWpsModelName(
+ struct wpa_supplicant* wpa_s, const std::string& model_name)
+{
+ WPA_ASSERT(wpa_s);
+ if (freeAndSetStringConfigParam(
+ wpa_s, model_name, kMaxWpsModelNameSize, CFG_CHANGED_WPS_STRING,
+ &wpa_s->conf->model_name)) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setWpsModelNumber(
+ struct wpa_supplicant* wpa_s, const std::string& model_number)
+{
+ WPA_ASSERT(wpa_s);
+ if (freeAndSetStringConfigParam(
+ wpa_s, model_number, kMaxWpsModelNumberSize,
+ CFG_CHANGED_WPS_STRING, &wpa_s->conf->model_number)) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setWpsSerialNumber(
+ struct wpa_supplicant* wpa_s, const std::string& serial_number)
+{
+ WPA_ASSERT(wpa_s);
+ if (freeAndSetStringConfigParam(
+ wpa_s, serial_number, kMaxWpsSerialNumberSize,
+ CFG_CHANGED_WPS_STRING, &wpa_s->conf->serial_number)) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setWpsConfigMethods(
+ struct wpa_supplicant* wpa_s, uint16_t config_methods)
+{
+ WPA_ASSERT(wpa_s);
+ if (freeAndSetStringConfigParam(
+ wpa_s, convertWpsConfigMethodsMaskToString(config_methods),
+ UINT32_MAX, CFG_CHANGED_CONFIG_METHODS,
+ &wpa_s->conf->config_methods)) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus setExternalSim(
+ struct wpa_supplicant* wpa_s, bool useExternalSim)
+{
+ WPA_ASSERT(wpa_s);
+ wpa_s->conf->external_sim = useExternalSim ? 1 : 0;
+ return ndk::ScopedAStatus::ok();
+}
+} // namespace iface_config_utils
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wpa_supplicant/aidl/iface_config_utils.h b/wpa_supplicant/aidl/iface_config_utils.h
new file mode 100644
index 0000000..c17dbb4
--- /dev/null
+++ b/wpa_supplicant/aidl/iface_config_utils.h
@@ -0,0 +1,55 @@
+/*
+ * WPA Supplicant - Iface configuration methods
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_IFACE_CONFIG_UTILS_H
+#define WPA_SUPPLICANT_AIDL_IFACE_CONFIG_UTILS_H
+
+#include <android-base/macros.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+#include "config.h"
+}
+
+/**
+ * Utility functions to set various config parameters of an iface via AIDL
+ * methods.
+ */
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace iface_config_utils {
+ndk::ScopedAStatus setWpsDeviceName(
+ struct wpa_supplicant* wpa_s, const std::string& name);
+ndk::ScopedAStatus setWpsDeviceType(
+ struct wpa_supplicant* wpa_s, const std::array<uint8_t, 8>& type);
+ndk::ScopedAStatus setWpsManufacturer(
+ struct wpa_supplicant* wpa_s, const std::string& manufacturer);
+ndk::ScopedAStatus setWpsModelName(
+ struct wpa_supplicant* wpa_s, const std::string& model_name);
+ndk::ScopedAStatus setWpsModelNumber(
+ struct wpa_supplicant* wpa_s, const std::string& model_number);
+ndk::ScopedAStatus setWpsSerialNumber(
+ struct wpa_supplicant* wpa_s, const std::string& serial_number);
+ndk::ScopedAStatus setWpsConfigMethods(
+ struct wpa_supplicant* wpa_s, uint16_t config_methods);
+ndk::ScopedAStatus setExternalSim(
+ struct wpa_supplicant* wpa_s, bool useExternalSim);
+} // namespace iface_config_utils
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WPA_SUPPLICANT_AIDL_IFACE_CONFIG_UTILS_H
diff --git a/wpa_supplicant/aidl/misc_utils.h b/wpa_supplicant/aidl/misc_utils.h
new file mode 100644
index 0000000..5c5b68c
--- /dev/null
+++ b/wpa_supplicant/aidl/misc_utils.h
@@ -0,0 +1,127 @@
+/*
+ * WPA Supplicant - Helper methods for Aidl
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef MISC_UTILS_H_
+#define MISC_UTILS_H_
+
+#include <iostream>
+#include <aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.h>
+
+extern "C"
+{
+#include "wpabuf.h"
+}
+
+namespace {
+constexpr size_t kWpsPinNumDigits = 8;
+// Custom deleter for wpabuf.
+void freeWpaBuf(wpabuf *ptr) { wpabuf_free(ptr); }
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace misc_utils {
+using wpabuf_unique_ptr = std::unique_ptr<wpabuf, void (*)(wpabuf *)>;
+
+// Creates a unique_ptr for wpabuf ptr with a custom deleter.
+inline wpabuf_unique_ptr createWpaBufUniquePtr(struct wpabuf *raw_ptr)
+{
+ return {raw_ptr, freeWpaBuf};
+}
+
+// Creates a wpabuf ptr with a custom deleter copying the data from the provided
+// vector.
+inline wpabuf_unique_ptr convertVectorToWpaBuf(const std::vector<uint8_t> &data)
+{
+ return createWpaBufUniquePtr(
+ wpabuf_alloc_copy(data.data(), data.size()));
+}
+
+// Copies the provided wpabuf contents to a std::vector.
+inline std::vector<uint8_t> convertWpaBufToVector(const struct wpabuf *buf)
+{
+ if (buf) {
+ return std::vector<uint8_t>(
+ wpabuf_head_u8(buf), wpabuf_head_u8(buf) + wpabuf_len(buf));
+ } else {
+ return std::vector<uint8_t>();
+ }
+}
+
+// Returns a string holding the wps pin.
+inline std::string convertWpsPinToString(int pin)
+{
+ char pin_str[kWpsPinNumDigits + 1];
+ snprintf(pin_str, sizeof(pin_str), "%08d", pin);
+ return pin_str;
+}
+
+// Wrappers to create a ScopedAStatus using a SupplicantStatusCode
+inline ndk::ScopedAStatus createStatus(SupplicantStatusCode status_code) {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(status_code));
+}
+
+inline ndk::ScopedAStatus createStatusWithMsg(
+ SupplicantStatusCode status_code, std::string msg)
+{
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ static_cast<int32_t>(status_code), msg.c_str());
+}
+
+// Creates an std::string from a char*, which could be null
+inline std::string charBufToString(const char* buf) {
+ return buf ? std::string(buf) : "";
+}
+
+inline std::stringstream& serializePmkCacheEntry(
+ std::stringstream &ss, struct rsn_pmksa_cache_entry *pmksa_entry) {
+ ss.write((char *) &pmksa_entry->pmk_len, sizeof(pmksa_entry->pmk_len));
+ ss.write((char *) pmksa_entry->pmk, pmksa_entry->pmk_len);
+ ss.write((char *) pmksa_entry->pmkid, PMKID_LEN);
+ ss.write((char *) pmksa_entry->aa, ETH_ALEN);
+ // Omit wpa_ssid field because the network is created on connecting to a access point.
+ ss.write((char *) &pmksa_entry->akmp, sizeof(pmksa_entry->akmp));
+ ss.write((char *) &pmksa_entry->reauth_time, sizeof(pmksa_entry->reauth_time));
+ ss.write((char *) &pmksa_entry->expiration, sizeof(pmksa_entry->expiration));
+ ss.write((char *) &pmksa_entry->opportunistic, sizeof(pmksa_entry->opportunistic));
+ char byte = (pmksa_entry->fils_cache_id_set) ? 1 : 0;
+ ss.write((char *) &byte, sizeof(byte));
+ ss.write((char *) pmksa_entry->fils_cache_id, FILS_CACHE_ID_LEN);
+ ss << std::flush;
+ return ss;
+}
+
+inline std::stringstream& deserializePmkCacheEntry(
+ std::stringstream &ss, struct rsn_pmksa_cache_entry *pmksa_entry) {
+ ss.seekg(0);
+ ss.read((char *) &pmksa_entry->pmk_len, sizeof(pmksa_entry->pmk_len));
+ ss.read((char *) pmksa_entry->pmk, pmksa_entry->pmk_len);
+ ss.read((char *) pmksa_entry->pmkid, PMKID_LEN);
+ ss.read((char *) pmksa_entry->aa, ETH_ALEN);
+ // Omit wpa_ssid field because the network is created on connecting to a access point.
+ ss.read((char *) &pmksa_entry->akmp, sizeof(pmksa_entry->akmp));
+ ss.read((char *) &pmksa_entry->reauth_time, sizeof(pmksa_entry->reauth_time));
+ ss.read((char *) &pmksa_entry->expiration, sizeof(pmksa_entry->expiration));
+ ss.read((char *) &pmksa_entry->opportunistic, sizeof(pmksa_entry->opportunistic));
+ char byte = 0;
+ ss.read((char *) &byte, sizeof(byte));
+ pmksa_entry->fils_cache_id_set = (byte) ? 1 : 0;
+ ss.read((char *) pmksa_entry->fils_cache_id, FILS_CACHE_ID_LEN);
+ return ss;
+}
+} // namespace misc_utils
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+#endif // MISC_UTILS_H_
diff --git a/wpa_supplicant/aidl/p2p_iface.cpp b/wpa_supplicant/aidl/p2p_iface.cpp
new file mode 100644
index 0000000..42b57e9
--- /dev/null
+++ b/wpa_supplicant/aidl/p2p_iface.cpp
@@ -0,0 +1,2028 @@
+/*
+ * WPA Supplicant - P2P Iface Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "aidl_manager.h"
+#include "aidl_return_util.h"
+#include "iface_config_utils.h"
+#include "misc_utils.h"
+#include "p2p_iface.h"
+#include "sta_network.h"
+
+extern "C"
+{
+#include "ap.h"
+#include "wps_supplicant.h"
+#include "wifi_display.h"
+#include "utils/eloop.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+}
+
+#define P2P_MAX_JOIN_SCAN_ATTEMPTS 3
+// Wait time before triggering the single channel scan to discover Auto GO.
+// Use a shorter wait time when the given frequency is GO operating frequency.
+// The idea is to quickly finish scans and return the status to application.
+#define P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS 200000
+// Wait time before triggering the multiple channel scan to discover Auto GO.
+#define P2P_JOIN_MULTIPLE_CHANNEL_SCAN_INTERVAL_USECS 1000000
+
+namespace {
+const char kConfigMethodStrPbc[] = "pbc";
+const char kConfigMethodStrDisplay[] = "display";
+const char kConfigMethodStrKeypad[] = "keypad";
+constexpr char kSetMiracastMode[] = "MIRACAST ";
+constexpr uint8_t kWfdDeviceInfoSubelemId = 0;
+constexpr uint8_t kWfdR2DeviceInfoSubelemId = 11;
+constexpr char kWfdDeviceInfoSubelemLenHexStr[] = "0006";
+
+std::function<void()> pending_join_scan_callback = NULL;
+std::function<void()> pending_scan_res_join_callback = NULL;
+
+using aidl::android::hardware::wifi::supplicant::ISupplicantP2pIface;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaNetwork;
+using aidl::android::hardware::wifi::supplicant::MiracastMode;
+
+uint8_t convertAidlMiracastModeToInternal(
+ MiracastMode mode)
+{
+ switch (mode) {
+ case MiracastMode::DISABLED:
+ return 0;
+ case MiracastMode::SOURCE:
+ return 1;
+ case MiracastMode::SINK:
+ return 2;
+ };
+ WPA_ASSERT(false);
+}
+
+/**
+ * Check if the provided ssid is valid or not.
+ *
+ * Returns 1 if valid, 0 otherwise.
+ */
+int isSsidValid(const std::vector<uint8_t>& ssid)
+{
+ if (ssid.size() == 0 ||
+ ssid.size() >
+ static_cast<uint32_t>(ISupplicantStaNetwork::
+ SSID_MAX_LEN_IN_BYTES)) {
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * Check if the provided psk passhrase is valid or not.
+ *
+ * Returns 1 if valid, 0 otherwise.
+ */
+int isPskPassphraseValid(const std::string &psk)
+{
+ if (psk.size() <
+ static_cast<uint32_t>(ISupplicantStaNetwork::
+ PSK_PASSPHRASE_MIN_LEN_IN_BYTES) ||
+ psk.size() >
+ static_cast<uint32_t>(ISupplicantStaNetwork::
+ PSK_PASSPHRASE_MAX_LEN_IN_BYTES)) {
+ return 0;
+ }
+ if (has_ctrl_char((u8 *)psk.c_str(), psk.size())) {
+ return 0;
+ }
+ return 1;
+}
+
+static int setBandScanFreqsList(
+ struct wpa_supplicant *wpa_s,
+ enum hostapd_hw_mode hw_mode,
+ bool exclude_dfs,
+ struct wpa_driver_scan_params *params)
+{
+ struct hostapd_hw_modes *mode;
+ int count, i;
+
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0);
+ if (mode == NULL || !mode->num_channels) {
+ wpa_printf(MSG_ERROR,
+ "P2P: No channels supported in this hw_mode: %d", hw_mode);
+ return -1;
+ }
+
+ /*
+ * Allocate memory for frequency array, allocate one extra
+ * slot for the zero-terminator.
+ */
+ params->freqs = (int *) os_calloc(mode->num_channels + 1, sizeof(int));
+ if (params->freqs == NULL) {
+ return -ENOMEM;
+ }
+ for (count = 0, i = 0; i < mode->num_channels; i++) {
+ if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) {
+ continue;
+ }
+ if (exclude_dfs && (mode->channels[i].flag & HOSTAPD_CHAN_RADAR)) {
+ continue;
+ }
+ params->freqs[count++] = mode->channels[i].freq;
+ }
+ if (!count && params->freqs) {
+ wpa_printf(MSG_ERROR,
+ "P2P: All channels(exclude_dfs: %d) are disabled in this hw_mode: %d",
+ exclude_dfs, hw_mode);
+ os_free(params->freqs);
+ return -1;
+ }
+ return 0;
+}
+
+static int setScanFreq(struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params,
+ int freq, int operating_freq)
+{
+ int frequency = operating_freq ? operating_freq : freq;
+ if (disabled_freq(wpa_s, frequency)) {
+ wpa_printf(MSG_ERROR,
+ "P2P: freq %d is not supported for a client.", frequency);
+ return -1;
+ }
+ /*
+ * Allocate memory for frequency array, with one extra
+ * slot for the zero-terminator.
+ */
+ params->freqs = new int[2] {frequency, 0};
+ return 0;
+}
+
+/**
+ * setP2pCliOptimizedScanFreqsList - Fill the frequencies to scan in Scan
+ * parameters.
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @params: Pointer to Scan parameters.
+ * @freq: Frequency/Band requested to scan by the application, possible values are,
+ * 0 - All the frequencies - full scan
+ * 2 - Frequencies in 2.4GHz
+ * 5 - Frequencies in 5GHz
+ * - Valid frequency
+ * @operating_freq: Frequency of BSS if found in scan cache
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ */
+static int setP2pCliOptimizedScanFreqsList(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params, int freq, int operating_freq)
+{
+ int ret;
+ /* If BSS is found in scan cache, first scan its operating frequency */
+ if (!wpa_s->p2p_join_scan_count && operating_freq) {
+ ret = setScanFreq(wpa_s, params, freq, operating_freq);
+ if (!ret) {
+ return ret;
+ }
+ }
+
+ /* Empty freq params means scan all the frequencies */
+ if (freq == 0) {
+ return 0;
+ }
+ else if (freq == 2 || freq == 5) {
+ /* Scan the frequencies in the band */
+ enum hostapd_hw_mode mode;
+ int ret;
+ if (wpa_s->hw.modes == NULL) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: Unknown what %dG channels the driver supports.", freq);
+ return 0;
+ }
+ mode = freq == 5 ? HOSTAPD_MODE_IEEE80211A : HOSTAPD_MODE_IEEE80211G;
+ if (wpa_s->p2p_join_scan_count < 2) {
+ // scan all non DFS channels in the first two attempts
+ ret = setBandScanFreqsList(wpa_s, mode, true, params);
+ if (ret < 0 && (-ENOMEM != ret)) {
+ // try to scan all channels before returning error
+ ret = setBandScanFreqsList(wpa_s, mode, false, params);
+ }
+ } else {
+ // scan all channels
+ ret = setBandScanFreqsList(wpa_s, mode, false, params);
+ }
+ return ret;
+ } else {
+ /* Scan the frequency requested by the application */
+ ret = setScanFreq(wpa_s, params, freq, 0);
+ return ret;
+ }
+ return 0;
+}
+
+/**
+ * getP2pJoinScanInterval - Get the delay in triggering the scan to discover
+ * Auto GO.
+ */
+static int getP2pJoinScanIntervalUsecs(int freq)
+{
+ if (freq == 5 || freq == 2 || freq == 0) {
+ return P2P_JOIN_MULTIPLE_CHANNEL_SCAN_INTERVAL_USECS;
+ } else {
+ return P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS;
+ }
+}
+
+/*
+ * isAnyEtherAddr - match any ether address
+ *
+ */
+int isAnyEtherAddr(const u8 *a)
+{
+ // 02:00:00:00:00:00
+ return (a[0] == 2) && !(a[1] | a[2] | a[3] | a[4] | a[5]);
+}
+
+/**
+ * findBssBySsid - Fetch a BSS table entry based on SSID and optional BSSID.
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @bssid: BSSID, 02:00:00:00:00:00 matches any bssid
+ * @ssid: SSID
+ * @ssid_len: Length of @ssid
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ */
+struct wpa_bss* findBssBySsid(
+ struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const u8 *ssid, size_t ssid_len)
+{
+ struct wpa_bss *bss;
+ dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+ if ((isAnyEtherAddr(bssid) ||
+ os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) &&
+ bss->ssid_len == ssid_len &&
+ os_memcmp(bss->ssid, ssid, ssid_len) == 0)
+ return bss;
+ }
+ return NULL;
+}
+
+/**
+ * findBssBySsidFromAnyInterface - Fetch a BSS table entry based on SSID and optional BSSID
+ * by iterating through all the interfaces.
+ * @head: Head of Pointer to wpa_supplicant data
+ * @bssid: BSSID, 02:00:00:00:00:00 matches any bssid
+ * @ssid: SSID
+ * @ssid_len: Length of @ssid
+ * Returns: Pointer to the BSS entry or %NULL if not found
+ */
+struct wpa_bss* findBssBySsidFromAnyInterface(
+ struct wpa_supplicant *head, const u8 *bssid,
+ const u8 *ssid, size_t ssid_len)
+{
+ struct wpa_supplicant *wpa_s;
+ struct wpa_bss *bss = NULL;
+ for (wpa_s = head; wpa_s; wpa_s = wpa_s->next) {
+ bss = findBssBySsid(wpa_s, bssid, ssid, ssid_len);
+ if (bss != NULL) {
+ return bss;
+ }
+ }
+ return bss;
+}
+
+struct wpa_ssid* addGroupClientNetwork(
+ struct wpa_supplicant* wpa_s,
+ uint8_t *group_owner_bssid,
+ const std::vector<uint8_t>& ssid,
+ const std::string& passphrase)
+{
+ struct wpa_ssid* wpa_network = wpa_config_add_network(wpa_s->conf);
+ if (!wpa_network) {
+ return NULL;
+ }
+ // set general network defaults
+ wpa_config_set_network_defaults(wpa_network);
+
+ // set P2p network defaults
+ wpa_network->p2p_group = 1;
+ wpa_network->mode = wpas_mode::WPAS_MODE_INFRA;
+
+ wpa_network->auth_alg = WPA_AUTH_ALG_OPEN;
+ wpa_network->key_mgmt = WPA_KEY_MGMT_PSK;
+ wpa_network->proto = WPA_PROTO_RSN;
+ wpa_network->pairwise_cipher = WPA_CIPHER_CCMP;
+ wpa_network->group_cipher = WPA_CIPHER_CCMP;
+ wpa_network->disabled = 2;
+
+ // set necessary fields
+ os_memcpy(wpa_network->bssid, group_owner_bssid, ETH_ALEN);
+ wpa_network->bssid_set = 1;
+
+ wpa_network->ssid = (uint8_t *)os_malloc(ssid.size());
+ if (wpa_network->ssid == NULL) {
+ wpa_config_remove_network(wpa_s->conf, wpa_network->id);
+ return NULL;
+ }
+ memcpy(wpa_network->ssid, ssid.data(), ssid.size());
+ wpa_network->ssid_len = ssid.size();
+
+ wpa_network->psk_set = 0;
+ wpa_network->passphrase = dup_binstr(passphrase.c_str(), passphrase.length());
+ if (wpa_network->passphrase == NULL) {
+ wpa_config_remove_network(wpa_s->conf, wpa_network->id);
+ return NULL;
+ }
+ wpa_config_update_psk(wpa_network);
+
+ return wpa_network;
+
+}
+
+void joinScanWrapper(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = (struct wpa_supplicant *) eloop_ctx;
+
+ if (pending_join_scan_callback != NULL) {
+ pending_join_scan_callback();
+ }
+}
+
+void scanResJoinWrapper(
+ struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *scan_res)
+{
+ if (wpa_s->p2p_scan_work) {
+ struct wpa_radio_work *work = wpa_s->p2p_scan_work;
+ wpa_s->p2p_scan_work = NULL;
+ radio_work_done(work);
+ }
+
+ if (pending_scan_res_join_callback) {
+ pending_scan_res_join_callback();
+ }
+}
+
+int joinScanReq(
+ struct wpa_supplicant* wpa_s,
+ const std::vector<uint8_t>& ssid,
+ int freq, int operating_freq)
+{
+ int ret;
+ struct wpa_driver_scan_params params;
+ struct wpabuf *ies;
+ size_t ielen;
+ unsigned int bands;
+
+ if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
+ wpa_printf(MSG_ERROR,
+ "P2P: P2P interface is gone, cancel join scan");
+ return -ENXIO;
+ }
+
+ os_memset(¶ms, 0, sizeof(params));
+ if (ssid.size() > 0) {
+ params.ssids[0].ssid = ssid.data();
+ params.ssids[0].ssid_len = ssid.size();
+ } else {
+ params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
+ params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
+ }
+ wpa_printf(MSG_DEBUG, "Scan SSID %s for join with frequency %d"
+ "BSS operating_freq from scan cache %d",
+ wpa_ssid_txt(params.ssids[0].ssid, params.ssids[0].ssid_len), freq, operating_freq);
+
+ /* Construct an optimized p2p scan channel list */
+ ret = setP2pCliOptimizedScanFreqsList(wpa_s, ¶ms, freq, operating_freq);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR,
+ "Failed to set frequency in p2p scan params, error = %d", ret);
+ return -1;
+ }
+
+ ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
+ ies = wpabuf_alloc(ielen);
+ if (ies == NULL) {
+ if (params.freqs) {
+ os_free(params.freqs);
+ }
+ return -1;
+ }
+
+ bands = wpas_get_bands(wpa_s, params.freqs);
+ p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands);
+
+ params.p2p_probe = 1;
+ params.extra_ies = (u8 *) wpabuf_head(ies);
+ params.extra_ies_len = wpabuf_len(ies);
+ if (wpa_s->clear_driver_scan_cache) {
+ wpa_printf(MSG_DEBUG,
+ "Request driver to clear scan cache due to local BSS flush");
+ params.only_new_results = 1;
+ }
+
+ ret = wpa_drv_scan(wpa_s, ¶ms);
+ if (!ret) {
+ os_get_reltime(&wpa_s->scan_trigger_time);
+ if (wpa_s->scan_res_handler) {
+ wpa_printf(MSG_DEBUG, "Replace current running scan result handler");
+ }
+ wpa_s->p2p_join_scan_count++;
+ wpa_s->scan_res_handler = scanResJoinWrapper;
+ wpa_s->own_scan_requested = 1;
+ wpa_s->clear_driver_scan_cache = 0;
+ }
+
+ if (params.freqs) {
+ os_free(params.freqs);
+ }
+
+ wpabuf_free(ies);
+
+ return ret;
+}
+
+int joinGroup(
+ struct wpa_supplicant* wpa_s,
+ uint8_t *group_owner_bssid,
+ const std::vector<uint8_t>& ssid,
+ const std::string& passphrase)
+{
+ int ret = 0;
+ int he = wpa_s->conf->p2p_go_he;
+ int vht = wpa_s->conf->p2p_go_vht;
+ int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+
+ // Construct a network for adding group.
+ // Group client follows the persistent attribute of Group Owner.
+ // If joined group is persistent, it adds a persistent network on GroupStarted.
+ struct wpa_ssid *wpa_network = addGroupClientNetwork(
+ wpa_s, group_owner_bssid, ssid, passphrase);
+ if (wpa_network == NULL) {
+ wpa_printf(MSG_ERROR, "P2P: Cannot construct a network for group join.");
+ return -1;
+ }
+
+ // this is temporary network only for establishing the connection.
+ wpa_network->temporary = 1;
+
+ if (wpas_p2p_group_add_persistent(
+ wpa_s, wpa_network, 0, 0, 0, 0, ht40, vht,
+ CHANWIDTH_USE_HT, he, 0, NULL, 0, 0)) {
+ ret = -1;
+ }
+
+ // Always remove this temporary network at the end.
+ wpa_config_remove_network(wpa_s->conf, wpa_network->id);
+ return ret;
+}
+
+void notifyGroupJoinFailure(
+ struct wpa_supplicant* wpa_s)
+{
+ u8 zero_addr[ETH_ALEN] = {0};
+ std::vector<uint8_t> ssid = {'D', 'I', 'R', 'E','C', 'T', '-'};
+ std::string passphrase = "";
+ struct wpa_ssid *wpa_network = addGroupClientNetwork(
+ wpa_s, zero_addr, ssid, passphrase);
+ if (wpa_network) {
+ wpa_network->temporary = 1;
+ wpas_notify_p2p_group_formation_failure(wpa_s, "Failed to find the group.");
+ wpas_notify_p2p_group_removed(
+ wpa_s, wpa_network, "client");
+ wpa_config_remove_network(
+ wpa_s->conf, wpa_network->id);
+ } else {
+ wpa_printf(MSG_ERROR,
+ "P2P: Cannot construct a network.");
+ }
+}
+
+void scanResJoinIgnore(struct wpa_supplicant *wpa_s, struct wpa_scan_results *scan_res) {
+ wpa_printf(MSG_DEBUG, "P2P: Ignore group join scan results.");
+
+ if (wpa_s->p2p_scan_work) {
+ struct wpa_radio_work *work = wpa_s->p2p_scan_work;
+ wpa_s->p2p_scan_work = NULL;
+ radio_work_done(work);
+ }
+
+}
+
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+using aidl_return_util::validateAndCall;
+using misc_utils::createStatus;
+using misc_utils::createStatusWithMsg;
+
+P2pIface::P2pIface(struct wpa_global* wpa_global, const char ifname[])
+ : wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
+{}
+
+void P2pIface::invalidate() { is_valid_ = false; }
+bool P2pIface::isValid()
+{
+ return (is_valid_ && (retrieveIfacePtr() != nullptr));
+}
+
+::ndk::ScopedAStatus P2pIface::getName(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::getNameInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::getType(
+ IfaceType* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::getTypeInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::addNetwork(
+ std::shared_ptr<ISupplicantP2pNetwork>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::addNetworkInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::removeNetwork(
+ int32_t in_id)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::removeNetworkInternal, in_id);
+}
+
+::ndk::ScopedAStatus P2pIface::getNetwork(
+ int32_t in_id, std::shared_ptr<ISupplicantP2pNetwork>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::getNetworkInternal, _aidl_return, in_id);
+}
+
+::ndk::ScopedAStatus P2pIface::listNetworks(
+ std::vector<int32_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::listNetworksInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::registerCallback(
+ const std::shared_ptr<ISupplicantP2pIfaceCallback>& in_callback)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::registerCallbackInternal, in_callback);
+}
+
+::ndk::ScopedAStatus P2pIface::getDeviceAddress(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::getDeviceAddressInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::setSsidPostfix(
+ const std::vector<uint8_t>& in_postfix)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setSsidPostfixInternal, in_postfix);
+}
+
+::ndk::ScopedAStatus P2pIface::setGroupIdle(
+ const std::string& in_groupIfName, int32_t in_timeoutInSec)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setGroupIdleInternal, in_groupIfName,
+ in_timeoutInSec);
+}
+
+::ndk::ScopedAStatus P2pIface::setPowerSave(
+ const std::string& in_groupIfName, bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setPowerSaveInternal, in_groupIfName, in_enable);
+}
+
+::ndk::ScopedAStatus P2pIface::find(
+ int32_t in_timeoutInSec)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::findInternal, in_timeoutInSec);
+}
+
+::ndk::ScopedAStatus P2pIface::stopFind()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::stopFindInternal);
+}
+
+::ndk::ScopedAStatus P2pIface::flush()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::flushInternal);
+}
+
+::ndk::ScopedAStatus P2pIface::connect(
+ const std::vector<uint8_t>& in_peerAddress,
+ WpsProvisionMethod in_provisionMethod,
+ const std::string& in_preSelectedPin, bool in_joinExistingGroup,
+ bool in_persistent, int32_t in_goIntent, std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::connectInternal, _aidl_return, in_peerAddress,
+ in_provisionMethod, in_preSelectedPin, in_joinExistingGroup,
+ in_persistent, in_goIntent);
+}
+
+::ndk::ScopedAStatus P2pIface::cancelConnect()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::cancelConnectInternal);
+}
+
+::ndk::ScopedAStatus P2pIface::provisionDiscovery(
+ const std::vector<uint8_t>& in_peerAddress,
+ WpsProvisionMethod in_provisionMethod)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::provisionDiscoveryInternal, in_peerAddress,
+ in_provisionMethod);
+}
+
+ndk::ScopedAStatus P2pIface::addGroup(
+ bool in_persistent, int32_t in_persistentNetworkId)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::addGroupInternal, in_persistent,
+ in_persistentNetworkId);
+}
+
+::ndk::ScopedAStatus P2pIface::addGroupWithConfig(
+ const std::vector<uint8_t>& in_ssid,
+ const std::string& in_pskPassphrase, bool in_persistent,
+ int32_t in_freq, const std::vector<uint8_t>& in_peerAddress,
+ bool in_joinExistingGroup)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::addGroupWithConfigInternal, in_ssid,
+ in_pskPassphrase, in_persistent, in_freq,
+ in_peerAddress, in_joinExistingGroup);
+}
+
+::ndk::ScopedAStatus P2pIface::removeGroup(
+ const std::string& in_groupIfName)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::removeGroupInternal, in_groupIfName);
+}
+
+::ndk::ScopedAStatus P2pIface::reject(
+ const std::vector<uint8_t>& in_peerAddress)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::rejectInternal, in_peerAddress);
+}
+
+::ndk::ScopedAStatus P2pIface::invite(
+ const std::string& in_groupIfName,
+ const std::vector<uint8_t>& in_goDeviceAddress,
+ const std::vector<uint8_t>& in_peerAddress)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::inviteInternal, in_groupIfName,
+ in_goDeviceAddress, in_peerAddress);
+}
+
+::ndk::ScopedAStatus P2pIface::reinvoke(
+ int32_t in_persistentNetworkId,
+ const std::vector<uint8_t>& in_peerAddress)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::reinvokeInternal, in_persistentNetworkId,
+ in_peerAddress);
+}
+
+::ndk::ScopedAStatus P2pIface::configureExtListen(
+ int32_t in_periodInMillis, int32_t in_intervalInMillis)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::configureExtListenInternal, in_periodInMillis,
+ in_intervalInMillis);
+}
+
+::ndk::ScopedAStatus P2pIface::setListenChannel(
+ int32_t in_channel, int32_t in_operatingClass)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setListenChannelInternal, in_channel,
+ in_operatingClass);
+}
+
+::ndk::ScopedAStatus P2pIface::setDisallowedFrequencies(
+ const std::vector<FreqRange>& in_ranges)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setDisallowedFrequenciesInternal, in_ranges);
+}
+
+::ndk::ScopedAStatus P2pIface::getSsid(
+ const std::vector<uint8_t>& in_peerAddress,
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::getSsidInternal, _aidl_return, in_peerAddress);
+}
+
+::ndk::ScopedAStatus P2pIface::getGroupCapability(
+ const std::vector<uint8_t>& in_peerAddress,
+ P2pGroupCapabilityMask* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::getGroupCapabilityInternal, _aidl_return, in_peerAddress);
+}
+
+::ndk::ScopedAStatus P2pIface::addBonjourService(
+ const std::vector<uint8_t>& in_query,
+ const std::vector<uint8_t>& in_response)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::addBonjourServiceInternal, in_query, in_response);
+}
+
+::ndk::ScopedAStatus P2pIface::removeBonjourService(
+ const std::vector<uint8_t>& in_query)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::removeBonjourServiceInternal, in_query);
+}
+
+::ndk::ScopedAStatus P2pIface::addUpnpService(
+ int32_t in_version, const std::string& in_serviceName)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::addUpnpServiceInternal, in_version, in_serviceName);
+}
+
+::ndk::ScopedAStatus P2pIface::removeUpnpService(
+ int32_t in_version, const std::string& in_serviceName)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::removeUpnpServiceInternal, in_version,
+ in_serviceName);
+}
+
+::ndk::ScopedAStatus P2pIface::flushServices()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::flushServicesInternal);
+}
+
+::ndk::ScopedAStatus P2pIface::requestServiceDiscovery(
+ const std::vector<uint8_t>& in_peerAddress,
+ const std::vector<uint8_t>& in_query,
+ int64_t* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::requestServiceDiscoveryInternal, _aidl_return,
+ in_peerAddress, in_query);
+}
+
+::ndk::ScopedAStatus P2pIface::cancelServiceDiscovery(
+ int64_t in_identifier)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::cancelServiceDiscoveryInternal, in_identifier);
+}
+
+::ndk::ScopedAStatus P2pIface::setMiracastMode(
+ MiracastMode in_mode)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setMiracastModeInternal, in_mode);
+}
+
+::ndk::ScopedAStatus P2pIface::startWpsPbc(
+ const std::string& in_groupIfName,
+ const std::vector<uint8_t>& in_bssid)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::startWpsPbcInternal, in_groupIfName, in_bssid);
+}
+
+::ndk::ScopedAStatus P2pIface::startWpsPinKeypad(
+ const std::string& in_groupIfName,
+ const std::string& in_pin)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::startWpsPinKeypadInternal, in_groupIfName, in_pin);
+}
+
+::ndk::ScopedAStatus P2pIface::startWpsPinDisplay(
+ const std::string& in_groupIfName,
+ const std::vector<uint8_t>& in_bssid,
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::startWpsPinDisplayInternal, _aidl_return,
+ in_groupIfName, in_bssid);
+}
+
+::ndk::ScopedAStatus P2pIface::cancelWps(
+ const std::string& in_groupIfName)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::cancelWpsInternal, in_groupIfName);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsDeviceName(
+ const std::string& in_name)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setWpsDeviceNameInternal, in_name);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsDeviceType(
+ const std::vector<uint8_t>& in_type)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setWpsDeviceTypeInternal, in_type);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsManufacturer(
+ const std::string& in_manufacturer)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setWpsManufacturerInternal, in_manufacturer);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsModelName(
+ const std::string& in_modelName)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setWpsModelNameInternal, in_modelName);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsModelNumber(
+ const std::string& in_modelNumber)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setWpsModelNumberInternal, in_modelNumber);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsSerialNumber(
+ const std::string& in_serialNumber)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setWpsSerialNumberInternal, in_serialNumber);
+}
+
+::ndk::ScopedAStatus P2pIface::setWpsConfigMethods(
+ WpsConfigMethods in_configMethods)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setWpsConfigMethodsInternal, in_configMethods);
+}
+
+::ndk::ScopedAStatus P2pIface::enableWfd(
+ bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::enableWfdInternal, in_enable);
+}
+
+::ndk::ScopedAStatus P2pIface::setWfdDeviceInfo(
+ const std::vector<uint8_t>& in_info)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setWfdDeviceInfoInternal, in_info);
+}
+
+::ndk::ScopedAStatus P2pIface::createNfcHandoverRequestMessage(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::createNfcHandoverRequestMessageInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::createNfcHandoverSelectMessage(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::createNfcHandoverSelectMessageInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::reportNfcHandoverResponse(
+ const std::vector<uint8_t>& in_request)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::reportNfcHandoverResponseInternal, in_request);
+}
+
+::ndk::ScopedAStatus P2pIface::reportNfcHandoverInitiation(
+ const std::vector<uint8_t>& in_select)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::reportNfcHandoverInitiationInternal, in_select);
+}
+
+::ndk::ScopedAStatus P2pIface::saveConfig()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::saveConfigInternal);
+}
+
+::ndk::ScopedAStatus P2pIface::setMacRandomization(
+ bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setMacRandomizationInternal, in_enable);
+}
+
+::ndk::ScopedAStatus P2pIface::setEdmg(
+ bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &P2pIface::setEdmgInternal, in_enable);
+}
+
+::ndk::ScopedAStatus P2pIface::getEdmg(
+ bool* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &P2pIface::getEdmgInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pIface::setWfdR2DeviceInfo(
+ const std::vector<uint8_t>& in_info)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &P2pIface::setWfdR2DeviceInfoInternal, in_info);
+}
+
+std::pair<std::string, ndk::ScopedAStatus> P2pIface::getNameInternal()
+{
+ return {ifname_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<IfaceType, ndk::ScopedAStatus> P2pIface::getTypeInternal()
+{
+ return {IfaceType::P2P, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::shared_ptr<ISupplicantP2pNetwork>, ndk::ScopedAStatus>
+P2pIface::addNetworkInternal()
+{
+ std::shared_ptr<ISupplicantP2pNetwork> network;
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ struct wpa_ssid* ssid = wpa_supplicant_add_network(wpa_s);
+ if (!ssid) {
+ return {network, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ AidlManager* aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager ||
+ aidl_manager->getP2pNetworkAidlObjectByIfnameAndNetworkId(
+ wpa_s->ifname, ssid->id, &network)) {
+ return {network, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {network, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::removeNetworkInternal(int32_t id)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ int result = wpa_supplicant_remove_network(wpa_s, id);
+ if (result == -1) {
+ return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
+ } else if (result != 0) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::shared_ptr<ISupplicantP2pNetwork>, ndk::ScopedAStatus>
+P2pIface::getNetworkInternal(int32_t id)
+{
+ std::shared_ptr<ISupplicantP2pNetwork> network;
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ struct wpa_ssid* ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (!ssid) {
+ return {network, createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN)};
+ }
+ AidlManager* aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager ||
+ aidl_manager->getP2pNetworkAidlObjectByIfnameAndNetworkId(
+ wpa_s->ifname, ssid->id, &network)) {
+ return {network, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {network, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<int32_t>, ndk::ScopedAStatus>
+P2pIface::listNetworksInternal()
+{
+ std::vector<int32_t> network_ids;
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ for (struct wpa_ssid* wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
+ wpa_ssid = wpa_ssid->next) {
+ network_ids.emplace_back(wpa_ssid->id);
+ }
+ return {std::move(network_ids), ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::registerCallbackInternal(
+ const std::shared_ptr<ISupplicantP2pIfaceCallback>& callback)
+{
+ AidlManager* aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager ||
+ aidl_manager->addP2pIfaceCallbackAidlObject(ifname_, callback)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+P2pIface::getDeviceAddressInternal()
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ std::vector<uint8_t> addr(
+ wpa_s->global->p2p_dev_addr,
+ wpa_s->global->p2p_dev_addr + ETH_ALEN);
+ return {addr, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::setSsidPostfixInternal(
+ const std::vector<uint8_t>& postfix)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (p2p_set_ssid_postfix(
+ wpa_s->global->p2p, postfix.data(), postfix.size())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setGroupIdleInternal(
+ const std::string& group_ifname, uint32_t timeout_in_sec)
+{
+ struct wpa_supplicant* wpa_group_s =
+ retrieveGroupIfacePtr(group_ifname);
+ if (!wpa_group_s) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+ }
+ wpa_group_s->conf->p2p_group_idle = timeout_in_sec;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setPowerSaveInternal(
+ const std::string& group_ifname, bool enable)
+{
+ struct wpa_supplicant* wpa_group_s =
+ retrieveGroupIfacePtr(group_ifname);
+ if (!wpa_group_s) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+ }
+ if (wpa_drv_set_p2p_powersave(wpa_group_s, enable, -1, -1)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::findInternal(uint32_t timeout_in_sec)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+ }
+ uint32_t search_delay = wpas_p2p_search_delay(wpa_s);
+ if (wpas_p2p_find(
+ wpa_s, timeout_in_sec, P2P_FIND_START_WITH_FULL, 0, nullptr,
+ nullptr, search_delay, 0, nullptr, 0)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::stopFindInternal()
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+ }
+ if (wpa_s->scan_res_handler == scanResJoinWrapper) {
+ wpa_printf(MSG_DEBUG, "P2P: Stop pending group scan for stopping find).");
+ pending_scan_res_join_callback = NULL;
+ wpa_s->scan_res_handler = scanResJoinIgnore;
+ }
+ wpas_p2p_stop_find(wpa_s);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::flushInternal()
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
+ wpa_s->force_long_sd = 0;
+ wpas_p2p_stop_find(wpa_s);
+ wpa_s->parent->p2ps_method_config_any = 0;
+ wpa_bss_flush(wpa_s);
+ if (wpa_s->global->p2p)
+ p2p_flush(wpa_s->global->p2p);
+ return ndk::ScopedAStatus::ok();
+}
+
+// This method only implements support for subset (needed by Android framework)
+// of parameters that can be specified for connect.
+std::pair<std::string, ndk::ScopedAStatus> P2pIface::connectInternal(
+ const std::vector<uint8_t>& peer_address,
+ WpsProvisionMethod provision_method,
+ const std::string& pre_selected_pin, bool join_existing_group,
+ bool persistent, uint32_t go_intent)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (go_intent > 15) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID)};
+ }
+ int go_intent_signed = join_existing_group ? -1 : go_intent;
+ p2p_wps_method wps_method = {};
+ switch (provision_method) {
+ case WpsProvisionMethod::PBC:
+ wps_method = WPS_PBC;
+ break;
+ case WpsProvisionMethod::DISPLAY:
+ wps_method = WPS_PIN_DISPLAY;
+ break;
+ case WpsProvisionMethod::KEYPAD:
+ wps_method = WPS_PIN_KEYPAD;
+ break;
+ }
+ int he = wpa_s->conf->p2p_go_he;
+ int vht = wpa_s->conf->p2p_go_vht;
+ int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+ const char* pin =
+ pre_selected_pin.length() > 0 ? pre_selected_pin.data() : nullptr;
+ bool auto_join = !join_existing_group;
+ int new_pin = wpas_p2p_connect(
+ wpa_s, peer_address.data(), pin, wps_method, persistent, auto_join,
+ join_existing_group, false, go_intent_signed, 0, 0, -1, false, ht40,
+ vht, CHANWIDTH_USE_HT, he, 0, nullptr, 0);
+ if (new_pin < 0) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ std::string pin_ret;
+ if (provision_method == WpsProvisionMethod::DISPLAY &&
+ pre_selected_pin.empty()) {
+ pin_ret = misc_utils::convertWpsPinToString(new_pin);
+ }
+ return {pin_ret, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::cancelConnectInternal()
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (wpa_s->scan_res_handler == scanResJoinWrapper) {
+ wpa_printf(MSG_DEBUG, "P2P: Stop pending group scan for canceling connect");
+ pending_scan_res_join_callback = NULL;
+ wpa_s->scan_res_handler = scanResJoinIgnore;
+ }
+ if (wpas_p2p_cancel(wpa_s)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::provisionDiscoveryInternal(
+ const std::vector<uint8_t>& peer_address,
+ WpsProvisionMethod provision_method)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ p2ps_provision* prov_param;
+ const char* config_method_str = nullptr;
+ switch (provision_method) {
+ case WpsProvisionMethod::PBC:
+ config_method_str = kConfigMethodStrPbc;
+ break;
+ case WpsProvisionMethod::DISPLAY:
+ config_method_str = kConfigMethodStrDisplay;
+ break;
+ case WpsProvisionMethod::KEYPAD:
+ config_method_str = kConfigMethodStrKeypad;
+ break;
+ }
+ if (wpas_p2p_prov_disc(
+ wpa_s, peer_address.data(), config_method_str,
+ WPAS_P2P_PD_FOR_GO_NEG, nullptr)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::removeGroupInternal(const std::string& group_ifname)
+{
+ struct wpa_supplicant* wpa_group_s =
+ retrieveGroupIfacePtr(group_ifname);
+ if (!wpa_group_s) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+ }
+ wpa_group_s->global->p2p_go_found_external_scan = 0;
+ if (wpas_p2p_group_remove(wpa_group_s, group_ifname.c_str())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::rejectInternal(
+ const std::vector<uint8_t>& peer_address)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+ }
+ if (wpas_p2p_reject(wpa_s, peer_address.data())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::inviteInternal(
+ const std::string& group_ifname,
+ const std::vector<uint8_t>& go_device_address,
+ const std::vector<uint8_t>& peer_address)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (wpas_p2p_invite_group(
+ wpa_s, group_ifname.c_str(), peer_address.data(),
+ go_device_address.data())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::reinvokeInternal(
+ int32_t persistent_network_id,
+ const std::vector<uint8_t>& peer_address)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ int he = wpa_s->conf->p2p_go_he;
+ int vht = wpa_s->conf->p2p_go_vht;
+ int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+ struct wpa_ssid* ssid =
+ wpa_config_get_network(wpa_s->conf, persistent_network_id);
+ if (ssid == NULL || ssid->disabled != 2) {
+ return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
+ }
+ if (wpas_p2p_invite(
+ wpa_s, peer_address.data(), ssid, NULL, 0, 0, ht40, vht,
+ CHANWIDTH_USE_HT, 0, he, 0)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::configureExtListenInternal(
+ uint32_t period_in_millis, uint32_t interval_in_millis)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (wpas_p2p_ext_listen(wpa_s, period_in_millis, interval_in_millis)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setListenChannelInternal(
+ uint32_t channel, uint32_t operating_class)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (p2p_set_listen_channel(
+ wpa_s->global->p2p, operating_class, channel, 1)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setDisallowedFrequenciesInternal(
+ const std::vector<FreqRange>& ranges)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ using DestT = struct wpa_freq_range_list::wpa_freq_range;
+ DestT* freq_ranges = nullptr;
+ // Empty ranges is used to enable all frequencies.
+ if (ranges.size() != 0) {
+ freq_ranges = static_cast<DestT*>(
+ os_malloc(sizeof(DestT) * ranges.size()));
+ if (!freq_ranges) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ uint32_t i = 0;
+ for (const auto& range : ranges) {
+ freq_ranges[i].min = range.min;
+ freq_ranges[i].max = range.max;
+ i++;
+ }
+ }
+
+ os_free(wpa_s->global->p2p_disallow_freq.range);
+ wpa_s->global->p2p_disallow_freq.range = freq_ranges;
+ wpa_s->global->p2p_disallow_freq.num = ranges.size();
+ wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> P2pIface::getSsidInternal(
+ const std::vector<uint8_t>& peer_address)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ const struct p2p_peer_info* info =
+ p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0);
+ if (!info) {
+ return {std::vector<uint8_t>(),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ const struct p2p_device* dev =
+ reinterpret_cast<const struct p2p_device*>(
+ (reinterpret_cast<const uint8_t*>(info)) -
+ offsetof(struct p2p_device, info));
+ std::vector<uint8_t> ssid;
+ if (dev && dev->oper_ssid_len) {
+ ssid.assign(
+ dev->oper_ssid, dev->oper_ssid + dev->oper_ssid_len);
+ }
+ return {ssid, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<P2pGroupCapabilityMask, ndk::ScopedAStatus> P2pIface::getGroupCapabilityInternal(
+ const std::vector<uint8_t>& peer_address)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ const struct p2p_peer_info* info =
+ p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0);
+ if (!info) {
+ return {static_cast<P2pGroupCapabilityMask>(0),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {static_cast<P2pGroupCapabilityMask>(info->group_capab),
+ ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::addBonjourServiceInternal(
+ const std::vector<uint8_t>& query, const std::vector<uint8_t>& response)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ auto query_buf = misc_utils::convertVectorToWpaBuf(query);
+ auto response_buf = misc_utils::convertVectorToWpaBuf(response);
+ if (!query_buf || !response_buf) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ if (wpas_p2p_service_add_bonjour(
+ wpa_s, query_buf.get(), response_buf.get())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ // If successful, the wpabuf is referenced internally and hence should
+ // not be freed.
+ query_buf.release();
+ response_buf.release();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::removeBonjourServiceInternal(
+ const std::vector<uint8_t>& query)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ auto query_buf = misc_utils::convertVectorToWpaBuf(query);
+ if (!query_buf) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ if (wpas_p2p_service_del_bonjour(wpa_s, query_buf.get())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::addUpnpServiceInternal(
+ uint32_t version, const std::string& service_name)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (wpas_p2p_service_add_upnp(wpa_s, version, service_name.c_str())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::removeUpnpServiceInternal(
+ uint32_t version, const std::string& service_name)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (wpas_p2p_service_del_upnp(wpa_s, version, service_name.c_str())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::flushServicesInternal()
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ wpas_p2p_service_flush(wpa_s);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<uint64_t, ndk::ScopedAStatus> P2pIface::requestServiceDiscoveryInternal(
+ const std::vector<uint8_t>& peer_address,
+ const std::vector<uint8_t>& query)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ auto query_buf = misc_utils::convertVectorToWpaBuf(query);
+ if (!query_buf) {
+ return {0, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ const uint8_t* dst_addr = is_zero_ether_addr(peer_address.data())
+ ? nullptr
+ : peer_address.data();
+ uint64_t identifier =
+ wpas_p2p_sd_request(wpa_s, dst_addr, query_buf.get());
+ if (identifier == 0) {
+ return {0, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {identifier, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::cancelServiceDiscoveryInternal(uint64_t identifier)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (wpas_p2p_sd_cancel_request(wpa_s, identifier)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setMiracastModeInternal(
+ MiracastMode mode)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ uint8_t mode_internal = convertAidlMiracastModeToInternal(mode);
+ const std::string cmd_str =
+ kSetMiracastMode + std::to_string(mode_internal);
+ std::vector<char> cmd(
+ cmd_str.c_str(), cmd_str.c_str() + cmd_str.size() + 1);
+ char driver_cmd_reply_buf[4096] = {};
+ if (wpa_drv_driver_cmd(
+ wpa_s, cmd.data(), driver_cmd_reply_buf,
+ sizeof(driver_cmd_reply_buf))) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::startWpsPbcInternal(
+ const std::string& group_ifname, const std::vector<uint8_t>& bssid)
+{
+ struct wpa_supplicant* wpa_group_s =
+ retrieveGroupIfacePtr(group_ifname);
+ if (!wpa_group_s) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+ }
+ const uint8_t* bssid_addr =
+ is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+#ifdef CONFIG_AP
+ if (wpa_group_s->ap_iface) {
+ if (wpa_supplicant_ap_wps_pbc(wpa_group_s, bssid_addr, NULL)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+ }
+#endif /* CONFIG_AP */
+ if (wpas_wps_start_pbc(wpa_group_s, bssid_addr, 0, 0)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::startWpsPinKeypadInternal(
+ const std::string& group_ifname, const std::string& pin)
+{
+ struct wpa_supplicant* wpa_group_s =
+ retrieveGroupIfacePtr(group_ifname);
+ if (!wpa_group_s) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+ }
+#ifdef CONFIG_AP
+ if (wpa_group_s->ap_iface) {
+ if (wpa_supplicant_ap_wps_pin(
+ wpa_group_s, nullptr, pin.c_str(), nullptr, 0, 0) < 0) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+ }
+#endif /* CONFIG_AP */
+ if (wpas_wps_start_pin(
+ wpa_group_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::string, ndk::ScopedAStatus> P2pIface::startWpsPinDisplayInternal(
+ const std::string& group_ifname, const std::vector<uint8_t>& bssid)
+{
+ struct wpa_supplicant* wpa_group_s =
+ retrieveGroupIfacePtr(group_ifname);
+ if (!wpa_group_s) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN)};
+ }
+ const uint8_t* bssid_addr =
+ is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+ int pin = wpas_wps_start_pin(
+ wpa_group_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
+ if (pin < 0) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::convertWpsPinToString(pin), ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::cancelWpsInternal(const std::string& group_ifname)
+{
+ struct wpa_supplicant* wpa_group_s =
+ retrieveGroupIfacePtr(group_ifname);
+ if (!wpa_group_s) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+ }
+ if (wpas_wps_cancel(wpa_group_s)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setWpsDeviceNameInternal(const std::string& name)
+{
+ return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
+}
+
+ndk::ScopedAStatus P2pIface::setWpsDeviceTypeInternal(
+ const std::vector<uint8_t>& type)
+{
+ std::array<uint8_t, 8> type_arr;
+ std::copy_n(type.begin(), 8, type_arr.begin());
+ return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type_arr);
+}
+
+ndk::ScopedAStatus P2pIface::setWpsManufacturerInternal(
+ const std::string& manufacturer)
+{
+ return iface_config_utils::setWpsManufacturer(
+ retrieveIfacePtr(), manufacturer);
+}
+
+ndk::ScopedAStatus P2pIface::setWpsModelNameInternal(
+ const std::string& model_name)
+{
+ return iface_config_utils::setWpsModelName(
+ retrieveIfacePtr(), model_name);
+}
+
+ndk::ScopedAStatus P2pIface::setWpsModelNumberInternal(
+ const std::string& model_number)
+{
+ return iface_config_utils::setWpsModelNumber(
+ retrieveIfacePtr(), model_number);
+}
+
+ndk::ScopedAStatus P2pIface::setWpsSerialNumberInternal(
+ const std::string& serial_number)
+{
+ return iface_config_utils::setWpsSerialNumber(
+ retrieveIfacePtr(), serial_number);
+}
+
+ndk::ScopedAStatus P2pIface::setWpsConfigMethodsInternal(WpsConfigMethods config_methods)
+{
+
+ return iface_config_utils::setWpsConfigMethods(
+ retrieveIfacePtr(), static_cast<uint16_t>(config_methods));
+}
+
+ndk::ScopedAStatus P2pIface::enableWfdInternal(bool enable)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ wifi_display_enable(wpa_s->global, enable);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setWfdDeviceInfoInternal(
+ const std::vector<uint8_t>& info)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ std::vector<char> wfd_device_info_hex(info.size() * 2 + 1);
+ wpa_snprintf_hex(
+ wfd_device_info_hex.data(), wfd_device_info_hex.size(), info.data(),
+ info.size());
+ // |wifi_display_subelem_set| expects the first 2 bytes
+ // to hold the lenght of the subelement. In this case it's
+ // fixed to 6, so prepend that.
+ std::string wfd_device_info_set_cmd_str =
+ std::to_string(kWfdDeviceInfoSubelemId) + " " +
+ kWfdDeviceInfoSubelemLenHexStr + wfd_device_info_hex.data();
+ std::vector<char> wfd_device_info_set_cmd(
+ wfd_device_info_set_cmd_str.c_str(),
+ wfd_device_info_set_cmd_str.c_str() +
+ wfd_device_info_set_cmd_str.size() + 1);
+ if (wifi_display_subelem_set(
+ wpa_s->global, wfd_device_info_set_cmd.data())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+P2pIface::createNfcHandoverRequestMessageInternal()
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ auto buf = misc_utils::createWpaBufUniquePtr(
+ wpas_p2p_nfc_handover_req(wpa_s, 1));
+ if (!buf) {
+ return {std::vector<uint8_t>(),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::convertWpaBufToVector(buf.get()),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+P2pIface::createNfcHandoverSelectMessageInternal()
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ auto buf = misc_utils::createWpaBufUniquePtr(
+ wpas_p2p_nfc_handover_sel(wpa_s, 1, 0));
+ if (!buf) {
+ return {std::vector<uint8_t>(),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::convertWpaBufToVector(buf.get()),
+ ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::reportNfcHandoverResponseInternal(
+ const std::vector<uint8_t>& request)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ auto req = misc_utils::convertVectorToWpaBuf(request);
+ auto sel = misc_utils::convertVectorToWpaBuf(std::vector<uint8_t>{0});
+ if (!req || !sel) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+
+ if (wpas_p2p_nfc_report_handover(wpa_s, 0, req.get(), sel.get(), 0)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::reportNfcHandoverInitiationInternal(
+ const std::vector<uint8_t>& select)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ auto req = misc_utils::convertVectorToWpaBuf(std::vector<uint8_t>{0});
+ auto sel = misc_utils::convertVectorToWpaBuf(select);
+ if (!req || !sel) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+
+ if (wpas_p2p_nfc_report_handover(wpa_s, 1, req.get(), sel.get(), 0)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::saveConfigInternal()
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ if (!wpa_s->conf->update_config) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::addGroupInternal(
+ bool persistent, int32_t persistent_network_id)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ int he = wpa_s->conf->p2p_go_he;
+ int vht = wpa_s->conf->p2p_go_vht;
+ int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+ struct wpa_ssid* ssid =
+ wpa_config_get_network(wpa_s->conf, persistent_network_id);
+ if (ssid == NULL) {
+ if (wpas_p2p_group_add(
+ wpa_s, persistent, 0, 0, ht40, vht,
+ CHANWIDTH_USE_HT, he, 0)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ } else {
+ return ndk::ScopedAStatus::ok();
+ }
+ } else if (ssid->disabled == 2) {
+ if (wpas_p2p_group_add_persistent(
+ wpa_s, ssid, 0, 0, 0, 0, ht40, vht,
+ CHANWIDTH_USE_HT, he, 0, NULL, 0, 0)) {
+ return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
+ } else {
+ return ndk::ScopedAStatus::ok();
+ }
+ }
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+}
+
+ndk::ScopedAStatus P2pIface::addGroupWithConfigInternal(
+ const std::vector<uint8_t>& ssid, const std::string& passphrase,
+ bool persistent, uint32_t freq, const std::vector<uint8_t>& peer_address,
+ bool joinExistingGroup)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ int he = wpa_s->conf->p2p_go_he;
+ int vht = wpa_s->conf->p2p_go_vht;
+ int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+
+ if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+ }
+
+ if (!isSsidValid(ssid)) {
+ return createStatusWithMsg(SupplicantStatusCode::FAILURE_ARGS_INVALID,
+ "SSID is invalid.");
+ }
+
+ if (!isPskPassphraseValid(passphrase)) {
+ return createStatusWithMsg(SupplicantStatusCode::FAILURE_ARGS_INVALID,
+ "Passphrase is invalid.");
+ }
+
+ if (!joinExistingGroup) {
+ struct p2p_data *p2p = wpa_s->global->p2p;
+ os_memcpy(p2p->ssid, ssid.data(), ssid.size());
+ p2p->ssid_len = ssid.size();
+ p2p->ssid_set = 1;
+
+ os_memset(p2p->passphrase, 0, sizeof(p2p->passphrase));
+ os_memcpy(p2p->passphrase, passphrase.c_str(), passphrase.length());
+ p2p->passphrase_set = 1;
+
+ if (wpas_p2p_group_add(
+ wpa_s, persistent, freq, 0, ht40, vht,
+ CHANWIDTH_USE_HT, he, 0)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+ }
+
+ // The rest is for group join.
+ wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND before group join.");
+ wpas_p2p_stop_find(wpa_s);
+
+ if (pending_scan_res_join_callback != NULL) {
+ wpa_printf(MSG_WARNING, "P2P: Renew scan result callback with new request.");
+ }
+
+ pending_join_scan_callback =
+ [wpa_s, ssid, peer_address, freq]() {
+ if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
+ return;
+ }
+ int operating_freq = 0;
+ struct wpa_bss *bss = findBssBySsidFromAnyInterface(
+ wpa_s->global->ifaces, peer_address.data(), ssid.data(), ssid.size());
+ if (bss != NULL) {
+ wpa_printf(MSG_DEBUG, "P2P: Found Group owner " MACSTR "in scan cache",
+ MAC2STR(bss->bssid));
+ operating_freq = bss->freq;
+ }
+
+ int ret = joinScanReq(wpa_s, ssid, freq, operating_freq);
+ // for BUSY case, the scan might be occupied by WiFi.
+ // Do not give up immediately, but try again later.
+ if (-EBUSY == ret) {
+ // re-schedule this join scan
+ eloop_cancel_timeout(joinScanWrapper, wpa_s, NULL);
+ eloop_register_timeout(0, P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS,
+ joinScanWrapper, wpa_s, NULL);
+ } else if (0 != ret) {
+ notifyGroupJoinFailure(wpa_s);
+ pending_scan_res_join_callback = NULL;
+ }
+ };
+
+ pending_scan_res_join_callback = [wpa_s, ssid, passphrase, peer_address, freq, this]() {
+ if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "P2P: Scan results received for join (reinvoke).");
+
+ struct wpa_bss *bss = findBssBySsid(
+ wpa_s, peer_address.data(), ssid.data(), ssid.size());
+ if (bss) {
+ wpa_s->global->p2p_go_found_external_scan = 1;
+ if (0 != joinGroup(wpa_s, bss->bssid, ssid, passphrase)) {
+ wpa_printf(MSG_ERROR, "P2P: Failed to join a group.");
+ wpa_s->global->p2p_go_found_external_scan = 0;
+ }
+ // no need to notify group join failure here,
+ // it will be handled by wpas_p2p_group_add_persistent
+ // called in joinGroup.
+ pending_scan_res_join_callback = NULL;
+ return;
+ }
+ wpa_printf(MSG_DEBUG, "P2P: Join scan count %d.", wpa_s->p2p_join_scan_count);
+ eloop_cancel_timeout(joinScanWrapper, wpa_s, NULL);
+ if (wpa_s->p2p_join_scan_count < P2P_MAX_JOIN_SCAN_ATTEMPTS) {
+ wpa_printf(MSG_DEBUG, "P2P: Try join again later.");
+ eloop_register_timeout(0, getP2pJoinScanIntervalUsecs(freq),
+ joinScanWrapper, wpa_s, this);
+ return;
+ }
+
+ wpa_printf(MSG_ERROR, "P2P: Failed to find the group with "
+ "network name %s - stop join attempt",
+ ssid.data());
+ notifyGroupJoinFailure(wpa_s);
+ pending_scan_res_join_callback = NULL;
+ };
+
+ wpa_s->p2p_join_scan_count = 0;
+ pending_join_scan_callback();
+ if (pending_scan_res_join_callback == NULL) {
+ return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+ "Failed to start scan.");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setMacRandomizationInternal(bool enable)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ bool currentEnabledState = !!wpa_s->conf->p2p_device_random_mac_addr;
+ u8 *addr = NULL;
+
+ // The same state, no change is needed.
+ if (currentEnabledState == enable) {
+ wpa_printf(MSG_DEBUG, "The random MAC is %s already.",
+ (enable) ? "enabled" : "disabled");
+ return ndk::ScopedAStatus::ok();
+ }
+
+ if (enable) {
+ wpa_s->conf->p2p_device_random_mac_addr = 1;
+ wpa_s->conf->p2p_interface_random_mac_addr = 1;
+
+ // restore config if it failed to set up MAC address.
+ if (wpas_p2p_mac_setup(wpa_s) < 0) {
+ wpa_s->conf->p2p_device_random_mac_addr = 0;
+ wpa_s->conf->p2p_interface_random_mac_addr = 0;
+ return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+ "Failed to set up MAC address.");
+ }
+ } else {
+ // disable random MAC will use original MAC address
+ // regardless of any saved persistent groups.
+ if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
+ wpa_printf(MSG_ERROR, "Failed to restore MAC address");
+ return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+ "Failed to restore MAC address.");
+ }
+
+ if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
+ wpa_printf(MSG_INFO, "Could not update MAC address information");
+ return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+ "Failed to update MAC address.");
+ }
+ wpa_s->conf->p2p_device_random_mac_addr = 0;
+ wpa_s->conf->p2p_interface_random_mac_addr = 0;
+ }
+
+ // update internal data to send out correct device address in action frame.
+ os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
+ os_memcpy(wpa_s->global->p2p->cfg->dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::setEdmgInternal(bool enable)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ wpa_printf(MSG_DEBUG, "set p2p_go_edmg to %d", enable);
+ wpa_s->conf->p2p_go_edmg = enable ? 1 : 0;
+ wpa_s->p2p_go_edmg = enable ? 1 : 0;
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<bool, ndk::ScopedAStatus> P2pIface::getEdmgInternal()
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ return {(wpa_s->p2p_go_edmg == 1), ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pIface::setWfdR2DeviceInfoInternal(
+ const std::vector<uint8_t>& info)
+{
+ struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+ uint32_t wfd_r2_device_info_hex_len = info.size() * 2 + 1;
+ std::vector<char> wfd_r2_device_info_hex(wfd_r2_device_info_hex_len);
+ wpa_snprintf_hex(
+ wfd_r2_device_info_hex.data(), wfd_r2_device_info_hex.size(),
+ info.data(),info.size());
+ std::string wfd_r2_device_info_set_cmd_str =
+ std::to_string(kWfdR2DeviceInfoSubelemId) + " " +
+ wfd_r2_device_info_hex.data();
+ std::vector<char> wfd_r2_device_info_set_cmd(
+ wfd_r2_device_info_set_cmd_str.c_str(),
+ wfd_r2_device_info_set_cmd_str.c_str() +
+ wfd_r2_device_info_set_cmd_str.size() + 1);
+ if (wifi_display_subelem_set(
+ wpa_s->global, wfd_r2_device_info_set_cmd.data())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this iface.
+ * If the underlying iface is removed, then all RPC method calls on this object
+ * will return failure.
+ */
+wpa_supplicant* P2pIface::retrieveIfacePtr()
+{
+ return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this group iface.
+ */
+wpa_supplicant* P2pIface::retrieveGroupIfacePtr(const std::string& group_ifname)
+{
+ return wpa_supplicant_get_iface(wpa_global_, group_ifname.c_str());
+}
+
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wpa_supplicant/aidl/p2p_iface.h b/wpa_supplicant/aidl/p2p_iface.h
new file mode 100644
index 0000000..d24645c
--- /dev/null
+++ b/wpa_supplicant/aidl/p2p_iface.h
@@ -0,0 +1,300 @@
+/*
+ * WPA Supplicant - P2P Iface Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_P2P_IFACE_H
+#define WPA_SUPPLICANT_AIDL_P2P_IFACE_H
+
+#include <array>
+#include <vector>
+
+#include <android-base/macros.h>
+
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantP2pIface.h>
+#include <aidl/android/hardware/wifi/supplicant/FreqRange.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.h>
+#include <aidl/android/hardware/wifi/supplicant/MiracastMode.h>
+#include <aidl/android/hardware/wifi/supplicant/WpsProvisionMethod.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "p2p/p2p.h"
+#include "p2p/p2p_i.h"
+#include "p2p_supplicant.h"
+#include "p2p_supplicant.h"
+#include "config.h"
+}
+
+#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+/**
+ * Implementation of P2pIface aidl object. Each unique aidl
+ * object is used for control operations on a specific interface
+ * controlled by wpa_supplicant.
+ */
+class P2pIface : public BnSupplicantP2pIface
+{
+public:
+ P2pIface(struct wpa_global* wpa_global, const char ifname[]);
+ ~P2pIface() override = default;
+ // Refer to |StaIface::invalidate()|.
+ void invalidate();
+ bool isValid();
+
+ // Aidl methods exposed.
+ ::ndk::ScopedAStatus getName(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getType(IfaceType* _aidl_return) override;
+ ::ndk::ScopedAStatus addNetwork(
+ std::shared_ptr<ISupplicantP2pNetwork>* _aidl_return) override;
+ ::ndk::ScopedAStatus removeNetwork(int32_t in_id) override;
+ ::ndk::ScopedAStatus getNetwork(
+ int32_t in_id, std::shared_ptr<ISupplicantP2pNetwork>* _aidl_return) override;
+ ::ndk::ScopedAStatus listNetworks(std::vector<int32_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus registerCallback(
+ const std::shared_ptr<ISupplicantP2pIfaceCallback>& in_callback) override;
+ ::ndk::ScopedAStatus getDeviceAddress(std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus setSsidPostfix(const std::vector<uint8_t>& in_postfix) override;
+ ::ndk::ScopedAStatus setGroupIdle(
+ const std::string& in_groupIfName, int32_t in_timeoutInSec) override;
+ ::ndk::ScopedAStatus setPowerSave(
+ const std::string& in_groupIfName, bool in_enable) override;
+ ::ndk::ScopedAStatus find(int32_t in_timeoutInSec) override;
+ ::ndk::ScopedAStatus stopFind() override;
+ ::ndk::ScopedAStatus flush() override;
+ ::ndk::ScopedAStatus connect(
+ const std::vector<uint8_t>& in_peerAddress, WpsProvisionMethod in_provisionMethod,
+ const std::string& in_preSelectedPin, bool in_joinExistingGroup,
+ bool in_persistent, int32_t in_goIntent, std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus cancelConnect() override;
+ ::ndk::ScopedAStatus provisionDiscovery(
+ const std::vector<uint8_t>& in_peerAddress,
+ WpsProvisionMethod in_provisionMethod) override;
+ ::ndk::ScopedAStatus addGroup(bool in_persistent, int32_t in_persistentNetworkId) override;
+ ::ndk::ScopedAStatus addGroupWithConfig(
+ const std::vector<uint8_t>& in_ssid, const std::string& in_pskPassphrase,
+ bool in_persistent, int32_t in_freq, const std::vector<uint8_t>& in_peerAddress,
+ bool in_joinExistingGroup) override;
+ ::ndk::ScopedAStatus removeGroup(const std::string& in_groupIfName) override;
+ ::ndk::ScopedAStatus reject(const std::vector<uint8_t>& in_peerAddress) override;
+ ::ndk::ScopedAStatus invite(
+ const std::string& in_groupIfName,
+ const std::vector<uint8_t>& in_goDeviceAddress,
+ const std::vector<uint8_t>& in_peerAddress) override;
+ ::ndk::ScopedAStatus reinvoke(
+ int32_t in_persistentNetworkId,
+ const std::vector<uint8_t>& in_peerAddress) override;
+ ::ndk::ScopedAStatus configureExtListen(
+ int32_t in_periodInMillis, int32_t in_intervalInMillis) override;
+ ::ndk::ScopedAStatus setListenChannel(
+ int32_t in_channel, int32_t in_operatingClass) override;
+ ::ndk::ScopedAStatus setDisallowedFrequencies(
+ const std::vector<FreqRange>& in_ranges) override;
+ ::ndk::ScopedAStatus getSsid(
+ const std::vector<uint8_t>& in_peerAddress,
+ std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus getGroupCapability(
+ const std::vector<uint8_t>& in_peerAddress,
+ P2pGroupCapabilityMask* _aidl_return) override;
+ ::ndk::ScopedAStatus addBonjourService(
+ const std::vector<uint8_t>& in_query,
+ const std::vector<uint8_t>& in_response) override;
+ ::ndk::ScopedAStatus removeBonjourService(
+ const std::vector<uint8_t>& in_query) override;
+ ::ndk::ScopedAStatus addUpnpService(
+ int32_t in_version, const std::string& in_serviceName) override;
+ ::ndk::ScopedAStatus removeUpnpService(
+ int32_t in_version, const std::string& in_serviceName) override;
+ ::ndk::ScopedAStatus flushServices() override;
+ ::ndk::ScopedAStatus requestServiceDiscovery(
+ const std::vector<uint8_t>& in_peerAddress,
+ const std::vector<uint8_t>& in_query, int64_t* _aidl_return) override;
+ ::ndk::ScopedAStatus cancelServiceDiscovery(int64_t in_identifier) override;
+ ::ndk::ScopedAStatus setMiracastMode(MiracastMode in_mode) override;
+ ::ndk::ScopedAStatus startWpsPbc(
+ const std::string& in_groupIfName,
+ const std::vector<uint8_t>& in_bssid) override;
+ ::ndk::ScopedAStatus startWpsPinKeypad(
+ const std::string& in_groupIfName, const std::string& in_pin) override;
+ ::ndk::ScopedAStatus startWpsPinDisplay(
+ const std::string& in_groupIfName,
+ const std::vector<uint8_t>& in_bssid,
+ std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus cancelWps(const std::string& in_groupIfName) override;
+ ::ndk::ScopedAStatus setWpsDeviceName(
+ const std::string& in_name) override;
+ ::ndk::ScopedAStatus setWpsDeviceType(
+ const std::vector<uint8_t>& in_type) override;
+ ::ndk::ScopedAStatus setWpsManufacturer(
+ const std::string& in_manufacturer) override;
+ ::ndk::ScopedAStatus setWpsModelName(
+ const std::string& in_modelName) override;
+ ::ndk::ScopedAStatus setWpsModelNumber(
+ const std::string& in_modelNumber) override;
+ ::ndk::ScopedAStatus setWpsSerialNumber(
+ const std::string& in_serialNumber) override;
+ ::ndk::ScopedAStatus setWpsConfigMethods(
+ WpsConfigMethods in_configMethods) override;
+ ::ndk::ScopedAStatus enableWfd(bool in_enable) override;
+ ::ndk::ScopedAStatus setWfdDeviceInfo(
+ const std::vector<uint8_t>& in_info) override;
+ ::ndk::ScopedAStatus createNfcHandoverRequestMessage(
+ std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus createNfcHandoverSelectMessage(
+ std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus reportNfcHandoverInitiation(
+ const std::vector<uint8_t>& in_select) override;
+ ::ndk::ScopedAStatus reportNfcHandoverResponse(
+ const std::vector<uint8_t>& in_request) override;
+ ::ndk::ScopedAStatus saveConfig() override;
+ ::ndk::ScopedAStatus setMacRandomization(bool in_enable) override;
+ ::ndk::ScopedAStatus setEdmg(bool in_enable) override;
+ ::ndk::ScopedAStatus getEdmg(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus setWfdR2DeviceInfo(
+ const std::vector<uint8_t>& in_info) override;
+
+private:
+ // Corresponding worker functions for the AIDL methods.
+ std::pair<std::string, ndk::ScopedAStatus> getNameInternal();
+ std::pair<IfaceType, ndk::ScopedAStatus> getTypeInternal();
+ std::pair<std::shared_ptr<ISupplicantP2pNetwork>, ndk::ScopedAStatus>
+ addNetworkInternal();
+ ndk::ScopedAStatus removeNetworkInternal(int32_t id);
+ std::pair<std::shared_ptr<ISupplicantP2pNetwork>, ndk::ScopedAStatus>
+ getNetworkInternal(int32_t id);
+ std::pair<std::vector<int32_t>, ndk::ScopedAStatus>
+ listNetworksInternal();
+ ndk::ScopedAStatus registerCallbackInternal(
+ const std::shared_ptr<ISupplicantP2pIfaceCallback>& callback);
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+ getDeviceAddressInternal();
+ ndk::ScopedAStatus setSsidPostfixInternal(
+ const std::vector<uint8_t>& postfix);
+ ndk::ScopedAStatus setGroupIdleInternal(
+ const std::string& group_ifname, uint32_t timeout_in_sec);
+ ndk::ScopedAStatus setPowerSaveInternal(
+ const std::string& group_ifname, bool enable);
+ ndk::ScopedAStatus findInternal(uint32_t timeout_in_sec);
+ ndk::ScopedAStatus stopFindInternal();
+ ndk::ScopedAStatus flushInternal();
+ std::pair<std::string, ndk::ScopedAStatus> connectInternal(
+ const std::vector<uint8_t>& peer_address,
+ WpsProvisionMethod provision_method,
+ const std::string& pre_selected_pin, bool join_existing_group,
+ bool persistent, uint32_t go_intent);
+ ndk::ScopedAStatus cancelConnectInternal();
+ ndk::ScopedAStatus provisionDiscoveryInternal(
+ const std::vector<uint8_t>& peer_address,
+ WpsProvisionMethod provision_method);
+ ndk::ScopedAStatus addGroupInternal(bool in_persistent, int32_t in_persistentNetworkId);
+ ndk::ScopedAStatus addGroupWithConfigInternal(
+ const std::vector<uint8_t>& ssid, const std::string& passphrase,
+ bool persistent, uint32_t freq, const std::vector<uint8_t>& peer_address,
+ bool joinExistingGroup);
+ ndk::ScopedAStatus removeGroupInternal(const std::string& group_ifname);
+ ndk::ScopedAStatus rejectInternal(
+ const std::vector<uint8_t>& peer_address);
+ ndk::ScopedAStatus inviteInternal(
+ const std::string& group_ifname,
+ const std::vector<uint8_t>& go_device_address,
+ const std::vector<uint8_t>& peer_address);
+ ndk::ScopedAStatus reinvokeInternal(
+ int32_t persistent_network_id,
+ const std::vector<uint8_t>& peer_address);
+ ndk::ScopedAStatus configureExtListenInternal(
+ uint32_t period_in_millis, uint32_t interval_in_millis);
+ ndk::ScopedAStatus setListenChannelInternal(
+ uint32_t channel, uint32_t operating_class);
+ ndk::ScopedAStatus setDisallowedFrequenciesInternal(
+ const std::vector<FreqRange>& ranges);
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getSsidInternal(
+ const std::vector<uint8_t>& peer_address);
+ std::pair<P2pGroupCapabilityMask, ndk::ScopedAStatus> getGroupCapabilityInternal(
+ const std::vector<uint8_t>& peer_address);
+ ndk::ScopedAStatus addBonjourServiceInternal(
+ const std::vector<uint8_t>& query,
+ const std::vector<uint8_t>& response);
+ ndk::ScopedAStatus removeBonjourServiceInternal(
+ const std::vector<uint8_t>& query);
+ ndk::ScopedAStatus addUpnpServiceInternal(
+ uint32_t version, const std::string& service_name);
+ ndk::ScopedAStatus removeUpnpServiceInternal(
+ uint32_t version, const std::string& service_name);
+ ndk::ScopedAStatus flushServicesInternal();
+ std::pair<uint64_t, ndk::ScopedAStatus> requestServiceDiscoveryInternal(
+ const std::vector<uint8_t>& peer_address,
+ const std::vector<uint8_t>& query);
+ ndk::ScopedAStatus cancelServiceDiscoveryInternal(uint64_t identifier);
+ ndk::ScopedAStatus setMiracastModeInternal(
+ MiracastMode mode);
+ ndk::ScopedAStatus startWpsPbcInternal(
+ const std::string& group_ifname,
+ const std::vector<uint8_t>& bssid);
+ ndk::ScopedAStatus startWpsPinKeypadInternal(
+ const std::string& group_ifname, const std::string& pin);
+ std::pair<std::string, ndk::ScopedAStatus> startWpsPinDisplayInternal(
+ const std::string& group_ifname,
+ const std::vector<uint8_t>& bssid);
+ ndk::ScopedAStatus cancelWpsInternal(const std::string& group_ifname);
+ ndk::ScopedAStatus setWpsDeviceNameInternal(const std::string& name);
+ ndk::ScopedAStatus setWpsDeviceTypeInternal(
+ const std::vector<uint8_t>& type);
+ ndk::ScopedAStatus setWpsManufacturerInternal(
+ const std::string& manufacturer);
+ ndk::ScopedAStatus setWpsModelNameInternal(const std::string& model_name);
+ ndk::ScopedAStatus setWpsModelNumberInternal(
+ const std::string& model_number);
+ ndk::ScopedAStatus setWpsSerialNumberInternal(
+ const std::string& serial_number);
+ ndk::ScopedAStatus setWpsConfigMethodsInternal(WpsConfigMethods config_methods);
+ ndk::ScopedAStatus enableWfdInternal(bool enable);
+ ndk::ScopedAStatus setWfdDeviceInfoInternal(
+ const std::vector<uint8_t>& info);
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+ createNfcHandoverRequestMessageInternal();
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+ createNfcHandoverSelectMessageInternal();
+ ndk::ScopedAStatus reportNfcHandoverResponseInternal(
+ const std::vector<uint8_t>& request);
+ ndk::ScopedAStatus reportNfcHandoverInitiationInternal(
+ const std::vector<uint8_t>& select);
+ ndk::ScopedAStatus saveConfigInternal();
+ ndk::ScopedAStatus setMacRandomizationInternal(bool enable);
+ ndk::ScopedAStatus setEdmgInternal(bool enable);
+ std::pair<bool, ndk::ScopedAStatus> getEdmgInternal();
+ ndk::ScopedAStatus setWfdR2DeviceInfoInternal(
+ const std::vector<uint8_t>& info);
+
+ struct wpa_supplicant* retrieveIfacePtr();
+ struct wpa_supplicant* retrieveGroupIfacePtr(
+ const std::string& group_ifname);
+
+ // Reference to the global wpa_struct. This is assumed to be valid for
+ // the lifetime of the process.
+ struct wpa_global* wpa_global_;
+ // Name of the iface this aidl object controls
+ const std::string ifname_;
+ bool is_valid_;
+
+ DISALLOW_COPY_AND_ASSIGN(P2pIface);
+};
+
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WPA_SUPPLICANT_AIDL_P2P_IFACE_H
diff --git a/wpa_supplicant/aidl/p2p_network.cpp b/wpa_supplicant/aidl/p2p_network.cpp
new file mode 100644
index 0000000..9288382
--- /dev/null
+++ b/wpa_supplicant/aidl/p2p_network.cpp
@@ -0,0 +1,252 @@
+/*
+ * WPA Supplicant - P2P network Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "aidl_manager.h"
+#include "aidl_return_util.h"
+#include "misc_utils.h"
+#include "p2p_network.h"
+
+extern "C"
+{
+#include "config_ssid.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+using aidl_return_util::validateAndCall;
+using misc_utils::createStatus;
+
+P2pNetwork::P2pNetwork(
+ struct wpa_global *wpa_global, const char ifname[], int network_id)
+ : wpa_global_(wpa_global),
+ ifname_(ifname),
+ network_id_(network_id),
+ is_valid_(true)
+{}
+
+void P2pNetwork::invalidate() { is_valid_ = false; }
+bool P2pNetwork::isValid()
+{
+ return (is_valid_ && (retrieveNetworkPtr() != nullptr));
+}
+
+::ndk::ScopedAStatus P2pNetwork::getId(
+ int32_t* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &P2pNetwork::getIdInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::getInterfaceName(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &P2pNetwork::getInterfaceNameInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::getType(
+ IfaceType* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &P2pNetwork::getTypeInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::getSsid(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &P2pNetwork::getSsidInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::getBssid(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &P2pNetwork::getBssidInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::isCurrent(
+ bool* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &P2pNetwork::isCurrentInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::isPersistent(
+ bool* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &P2pNetwork::isPersistentInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::isGroupOwner(
+ bool* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &P2pNetwork::isGroupOwnerInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus P2pNetwork::setClientList(
+ const std::vector<MacAddress>& in_clients)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &P2pNetwork::setClientListInternal, in_clients);
+}
+
+::ndk::ScopedAStatus P2pNetwork::getClientList(
+ std::vector<MacAddress>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &P2pNetwork::getClientListInternal, _aidl_return);
+}
+
+std::pair<uint32_t, ndk::ScopedAStatus> P2pNetwork::getIdInternal()
+{
+ return {network_id_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> P2pNetwork::getInterfaceNameInternal()
+{
+ return {ifname_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<IfaceType, ndk::ScopedAStatus> P2pNetwork::getTypeInternal()
+{
+ return {IfaceType::P2P, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> P2pNetwork::getSsidInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ std::vector<uint8_t> ssid(
+ wpa_ssid->ssid, wpa_ssid->ssid + wpa_ssid->ssid_len);
+ return {ssid, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+P2pNetwork::getBssidInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ std::vector<uint8_t> bssid;
+ if (wpa_ssid->bssid_set) {
+ bssid.assign(wpa_ssid->bssid, wpa_ssid->bssid + ETH_ALEN);
+ }
+ return {bssid, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> P2pNetwork::isCurrentInternal()
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ return {(wpa_s->current_ssid == wpa_ssid),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> P2pNetwork::isPersistentInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ return {(wpa_ssid->disabled == 2), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> P2pNetwork::isGroupOwnerInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ return {(wpa_ssid->mode == wpas_mode::WPAS_MODE_P2P_GO),
+ ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus P2pNetwork::setClientListInternal(
+ const std::vector<MacAddress> &clients)
+{
+ for (const auto &client : clients) {
+ if (client.data.size() != ETH_ALEN) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ }
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ os_free(wpa_ssid->p2p_client_list);
+ // Internal representation uses a generic MAC addr/mask storage format
+ // (even though the mask is always 0xFF'ed for p2p_client_list). So, the
+ // first 6 bytes holds the client MAC address and the next 6 bytes are
+ // OxFF'ed.
+ wpa_ssid->p2p_client_list =
+ (u8 *)os_malloc(ETH_ALEN * 2 * clients.size());
+ if (!wpa_ssid->p2p_client_list) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ u8 *list = wpa_ssid->p2p_client_list;
+ for (const auto &client : clients) {
+ os_memcpy(list, client.data.data(), ETH_ALEN);
+ list += ETH_ALEN;
+ os_memset(list, 0xFF, ETH_ALEN);
+ list += ETH_ALEN;
+ }
+ wpa_ssid->num_p2p_clients = clients.size();
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::vector<MacAddress>, ndk::ScopedAStatus>
+P2pNetwork::getClientListInternal()
+{
+ std::vector<MacAddress> clients;
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->p2p_client_list) {
+ return {clients, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ u8 *list = wpa_ssid->p2p_client_list;
+ for (size_t i = 0; i < wpa_ssid->num_p2p_clients; i++) {
+ MacAddress client = MacAddress{};
+ client.data = std::vector<uint8_t>(list, list + ETH_ALEN);
+ clients.emplace_back(client);
+ list += 2 * ETH_ALEN;
+ }
+ return {clients, ndk::ScopedAStatus::ok()};
+}
+
+/**
+ * Retrieve the underlying |wpa_ssid| struct pointer for
+ * this network.
+ * If the underlying network is removed or the interface
+ * this network belong to is removed, all RPC method calls
+ * on this object will return failure.
+ */
+struct wpa_ssid *P2pNetwork::retrieveNetworkPtr()
+{
+ wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (!wpa_s)
+ return nullptr;
+ return wpa_config_get_network(wpa_s->conf, network_id_);
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this network.
+ */
+struct wpa_supplicant *P2pNetwork::retrieveIfacePtr()
+{
+ return wpa_supplicant_get_iface(
+ (struct wpa_global *)wpa_global_, ifname_.c_str());
+}
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wpa_supplicant/aidl/p2p_network.h b/wpa_supplicant/aidl/p2p_network.h
new file mode 100644
index 0000000..3b7ec5a
--- /dev/null
+++ b/wpa_supplicant/aidl/p2p_network.h
@@ -0,0 +1,94 @@
+/*
+ * WPA Supplicant - P2P network Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_P2P_NETWORK_H
+#define WPA_SUPPLICANT_AIDL_P2P_NETWORK_H
+
+#include <android-base/macros.h>
+
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantP2pNetwork.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+/**
+ * Implementation of P2pNetwork aidl object. Each unique aidl
+ * object is used for control operations on a specific network
+ * controlled by wpa_supplicant.
+ */
+class P2pNetwork : public BnSupplicantP2pNetwork
+{
+public:
+ P2pNetwork(
+ struct wpa_global* wpa_global, const char ifname[], int network_id);
+ ~P2pNetwork() override = default;
+ // Refer to |StaIface::invalidate()|.
+ void invalidate();
+ bool isValid();
+
+ // Aidl methods exposed.
+ ::ndk::ScopedAStatus getId(int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus getInterfaceName(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getType(IfaceType* _aidl_return) override;
+ ::ndk::ScopedAStatus getSsid(std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus getBssid(std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus isCurrent(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus isPersistent(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus isGroupOwner(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus setClientList(
+ const std::vector<MacAddress>& in_clients) override;
+ ::ndk::ScopedAStatus getClientList(
+ std::vector<MacAddress>* _aidl_return) override;
+
+private:
+ // Corresponding worker functions for the AIDL methods.
+ std::pair<uint32_t, ndk::ScopedAStatus> getIdInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getInterfaceNameInternal();
+ std::pair<IfaceType, ndk::ScopedAStatus> getTypeInternal();
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getSsidInternal();
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getBssidInternal();
+ std::pair<bool, ndk::ScopedAStatus> isCurrentInternal();
+ std::pair<bool, ndk::ScopedAStatus> isPersistentInternal();
+ std::pair<bool, ndk::ScopedAStatus> isGroupOwnerInternal();
+ ndk::ScopedAStatus setClientListInternal(
+ const std::vector<MacAddress>& clients);
+ std::pair<std::vector<MacAddress>, ndk::ScopedAStatus>
+ getClientListInternal();
+
+ struct wpa_ssid* retrieveNetworkPtr();
+ struct wpa_supplicant* retrieveIfacePtr();
+
+ // Reference to the global wpa_struct. This is assumed to be valid
+ // for the lifetime of the process.
+ const struct wpa_global* wpa_global_;
+ // Name of the iface this network belongs to.
+ const std::string ifname_;
+ // Id of the network this aidl object controls.
+ const int network_id_;
+ bool is_valid_;
+
+ DISALLOW_COPY_AND_ASSIGN(P2pNetwork);
+};
+
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WPA_SUPPLICANT_AIDL_P2P_NETWORK_H
diff --git a/wpa_supplicant/aidl/sta_iface.cpp b/wpa_supplicant/aidl/sta_iface.cpp
new file mode 100644
index 0000000..7238267
--- /dev/null
+++ b/wpa_supplicant/aidl/sta_iface.cpp
@@ -0,0 +1,1757 @@
+/*
+ * WPA Supplicant - Sta Iface Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "aidl_manager.h"
+#include "aidl_return_util.h"
+#include "iface_config_utils.h"
+#include "misc_utils.h"
+#include "sta_iface.h"
+
+extern "C"
+{
+#include "utils/eloop.h"
+#include "gas_query.h"
+#include "interworking.h"
+#include "hs20_supplicant.h"
+#include "wps_supplicant.h"
+#include "dpp.h"
+#include "dpp_supplicant.h"
+#include "rsn_supp/wpa.h"
+#include "rsn_supp/pmksa_cache.h"
+}
+
+namespace {
+using aidl::android::hardware::wifi::supplicant::AidlManager;
+using aidl::android::hardware::wifi::supplicant::BtCoexistenceMode;
+using aidl::android::hardware::wifi::supplicant::ConnectionCapabilities;
+using aidl::android::hardware::wifi::supplicant::DppCurve;
+using aidl::android::hardware::wifi::supplicant::DppResponderBootstrapInfo;
+using aidl::android::hardware::wifi::supplicant::ISupplicant;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaIface;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaNetwork;
+using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
+using aidl::android::hardware::wifi::supplicant::LegacyMode;
+using aidl::android::hardware::wifi::supplicant::RxFilterType;
+using aidl::android::hardware::wifi::supplicant::SupplicantStatusCode;
+using aidl::android::hardware::wifi::supplicant::WifiTechnology;
+using aidl::android::hardware::wifi::supplicant::misc_utils::createStatus;
+
+// TODO (b/204810426): Import from wifi vendor AIDL interface when it exists
+enum WifiChannelWidthInMhz {
+ WIDTH_20 = 0,
+ WIDTH_40 = 1,
+ WIDTH_80 = 2,
+ WIDTH_160 = 3,
+ WIDTH_80P80 = 4,
+ WIDTH_5 = 5,
+ WIDTH_10 = 6,
+ WIDTH_INVALID = -1
+};
+
+constexpr uint32_t kMaxAnqpElems = 100;
+constexpr char kGetMacAddress[] = "MACADDR";
+constexpr char kStartRxFilter[] = "RXFILTER-START";
+constexpr char kStopRxFilter[] = "RXFILTER-STOP";
+constexpr char kAddRxFilter[] = "RXFILTER-ADD";
+constexpr char kRemoveRxFilter[] = "RXFILTER-REMOVE";
+constexpr char kSetBtCoexistenceMode[] = "BTCOEXMODE";
+constexpr char kSetBtCoexistenceScanStart[] = "BTCOEXSCAN-START";
+constexpr char kSetBtCoexistenceScanStop[] = "BTCOEXSCAN-STOP";
+constexpr char kSetSupendModeEnabled[] = "SETSUSPENDMODE 1";
+constexpr char kSetSupendModeDisabled[] = "SETSUSPENDMODE 0";
+constexpr char kSetCountryCode[] = "COUNTRY";
+constexpr uint32_t kExtRadioWorkDefaultTimeoutInSec =
+ static_cast<uint32_t>(ISupplicant::EXT_RADIO_WORK_TIMEOUT_IN_SECS);
+constexpr char kExtRadioWorkNamePrefix[] = "ext:";
+
+uint8_t convertAidlRxFilterTypeToInternal(
+ RxFilterType type)
+{
+ switch (type) {
+ case RxFilterType::V4_MULTICAST:
+ return 2;
+ case RxFilterType::V6_MULTICAST:
+ return 3;
+ };
+ WPA_ASSERT(false);
+}
+
+uint8_t convertAidlBtCoexModeToInternal(
+ BtCoexistenceMode mode)
+{
+ switch (mode) {
+ case BtCoexistenceMode::ENABLED:
+ return 0;
+ case BtCoexistenceMode::DISABLED:
+ return 1;
+ case BtCoexistenceMode::SENSE:
+ return 2;
+ };
+ WPA_ASSERT(false);
+}
+
+ndk::ScopedAStatus doZeroArgDriverCommand(
+ struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ std::vector<char> cmd_vec(cmd, cmd + strlen(cmd) + 1);
+ char driver_cmd_reply_buf[4096] = {};
+ if (wpa_drv_driver_cmd(
+ wpa_s, cmd_vec.data(), driver_cmd_reply_buf,
+ sizeof(driver_cmd_reply_buf))) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus doOneArgDriverCommand(
+ struct wpa_supplicant *wpa_s, const char *cmd, uint8_t arg)
+{
+ std::string cmd_str = std::string(cmd) + " " + std::to_string(arg);
+ return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
+}
+
+ndk::ScopedAStatus doOneArgDriverCommand(
+ struct wpa_supplicant *wpa_s, const char *cmd, const std::string &arg)
+{
+ std::string cmd_str = std::string(cmd) + " " + arg;
+ return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
+}
+
+void endExtRadioWork(struct wpa_radio_work *work)
+{
+ auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+ work->wpa_s->ext_work_in_progress = 0;
+ radio_work_done(work);
+ os_free(ework);
+}
+
+void extRadioWorkTimeoutCb(void *eloop_ctx, void *timeout_ctx)
+{
+ auto *work = static_cast<struct wpa_radio_work *>(eloop_ctx);
+ auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+ wpa_dbg(
+ work->wpa_s, MSG_DEBUG, "Timing out external radio work %u (%s)",
+ ework->id, work->type);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ WPA_ASSERT(aidl_manager);
+ aidl_manager->notifyExtRadioWorkTimeout(work->wpa_s, ework->id);
+
+ endExtRadioWork(work);
+}
+
+void startExtRadioWork(struct wpa_radio_work *work)
+{
+ auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+ work->wpa_s->ext_work_in_progress = 1;
+ if (!ework->timeout) {
+ ework->timeout = kExtRadioWorkDefaultTimeoutInSec;
+ }
+ eloop_register_timeout(
+ ework->timeout, 0, extRadioWorkTimeoutCb, work, nullptr);
+}
+
+void extRadioWorkStartCb(struct wpa_radio_work *work, int deinit)
+{
+ // deinit==1 is invoked during interface removal. Since the AIDL
+ // interface does not support interface addition/removal, we don't
+ // need to handle this scenario.
+ WPA_ASSERT(!deinit);
+
+ auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+ wpa_dbg(
+ work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
+ ework->id, ework->type);
+
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ WPA_ASSERT(aidl_manager);
+ aidl_manager->notifyExtRadioWorkStart(work->wpa_s, ework->id);
+
+ startExtRadioWork(work);
+}
+
+KeyMgmtMask convertWpaKeyMgmtCapabilitiesToAidl (
+ struct wpa_supplicant *wpa_s, struct wpa_driver_capa *capa) {
+
+ uint32_t mask = 0;
+ /* Logic from ctrl_iface.c, NONE and IEEE8021X have no capability
+ * flags and always enabled.
+ */
+ mask |=
+ (static_cast<uint32_t>(KeyMgmtMask::NONE) |
+ static_cast<uint32_t>(KeyMgmtMask::IEEE8021X));
+
+ if (capa->key_mgmt &
+ (WPA_DRIVER_CAPA_KEY_MGMT_WPA | WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
+ mask |= static_cast<uint32_t>(KeyMgmtMask::WPA_EAP);
+ }
+
+ if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
+ WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
+ mask |= static_cast<uint32_t>(KeyMgmtMask::WPA_PSK);
+ }
+#ifdef CONFIG_SUITEB192
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) {
+ mask |= static_cast<uint32_t>(KeyMgmtMask::SUITE_B_192);
+ }
+#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_OWE
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) {
+ mask |= static_cast<uint32_t>(KeyMgmtMask::OWE);
+ }
+#endif /* CONFIG_OWE */
+#ifdef CONFIG_SAE
+ if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) {
+ mask |= static_cast<uint32_t>(KeyMgmtMask::SAE);
+ }
+#endif /* CONFIG_SAE */
+#ifdef CONFIG_DPP
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) {
+ mask |= static_cast<uint32_t>(KeyMgmtMask::DPP);
+ }
+#endif
+#ifdef CONFIG_WAPI_INTERFACE
+ mask |= static_cast<uint32_t>(KeyMgmtMask::WAPI_PSK);
+ mask |= static_cast<uint32_t>(KeyMgmtMask::WAPI_CERT);
+#endif /* CONFIG_WAPI_INTERFACE */
+#ifdef CONFIG_FILS
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) {
+ mask |= static_cast<uint32_t>(KeyMgmtMask::FILS_SHA256);
+ }
+ if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) {
+ mask |= static_cast<uint32_t>(KeyMgmtMask::FILS_SHA384);
+ }
+#endif /* CONFIG_FILS */
+ return static_cast<KeyMgmtMask>(mask);
+}
+
+const std::string getDppListenChannel(struct wpa_supplicant *wpa_s, int32_t *listen_channel)
+{
+ struct hostapd_hw_modes *mode;
+ int chan44 = 0, chan149 = 0;
+ *listen_channel = 0;
+
+ /* Check if device support 2.4GHz band*/
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+ HOSTAPD_MODE_IEEE80211G, 0);
+ if (mode) {
+ *listen_channel = 6;
+ return "81/6";
+ }
+ /* Check if device support 5GHz band */
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
+ HOSTAPD_MODE_IEEE80211A, 0);
+ if (mode) {
+ for (int i = 0; i < mode->num_channels; i++) {
+ struct hostapd_channel_data *chan = &mode->channels[i];
+
+ if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+ HOSTAPD_CHAN_RADAR))
+ continue;
+ if (chan->freq == 5220)
+ chan44 = 1;
+ if (chan->freq == 5745)
+ chan149 = 1;
+ }
+ if (chan149) {
+ *listen_channel = 149;
+ return "124/149";
+ } else if (chan44) {
+ *listen_channel = 44;
+ return "115/44";
+ }
+ }
+
+ return "";
+}
+
+const std::string convertCurveTypeToName(DppCurve curve)
+{
+ switch (curve) {
+ case DppCurve::PRIME256V1:
+ return "prime256v1";
+ case DppCurve::SECP384R1:
+ return "secp384r1";
+ case DppCurve::SECP521R1:
+ return "secp521r1";
+ case DppCurve::BRAINPOOLP256R1:
+ return "brainpoolP256r1";
+ case DppCurve::BRAINPOOLP384R1:
+ return "brainpoolP384r1";
+ case DppCurve::BRAINPOOLP512R1:
+ return "brainpoolP512r1";
+ }
+ WPA_ASSERT(false);
+}
+
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+using aidl_return_util::validateAndCall;
+using misc_utils::createStatus;
+
+StaIface::StaIface(struct wpa_global *wpa_global, const char ifname[])
+ : wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
+{}
+
+void StaIface::invalidate() { is_valid_ = false; }
+bool StaIface::isValid()
+{
+ return (is_valid_ && (retrieveIfacePtr() != nullptr));
+}
+
+::ndk::ScopedAStatus StaIface::getName(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::getNameInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::getType(
+ IfaceType* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::getTypeInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::addNetwork(
+ std::shared_ptr<ISupplicantStaNetwork>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::addNetworkInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::removeNetwork(
+ int32_t in_id)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::removeNetworkInternal, in_id);
+}
+
+::ndk::ScopedAStatus StaIface::filsHlpFlushRequest()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::filsHlpFlushRequestInternal);
+}
+
+::ndk::ScopedAStatus StaIface::filsHlpAddRequest(
+ const std::vector<uint8_t>& in_dst_mac,
+ const std::vector<uint8_t>& in_pkt)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::filsHlpAddRequestInternal, in_dst_mac, in_pkt);
+}
+
+::ndk::ScopedAStatus StaIface::getNetwork(
+ int32_t in_id, std::shared_ptr<ISupplicantStaNetwork>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::getNetworkInternal, _aidl_return, in_id);
+}
+
+::ndk::ScopedAStatus StaIface::listNetworks(
+ std::vector<int32_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::listNetworksInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::registerCallback(
+ const std::shared_ptr<ISupplicantStaIfaceCallback>& in_callback)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::registerCallbackInternal, in_callback);
+}
+
+::ndk::ScopedAStatus StaIface::reassociate()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::reassociateInternal);
+}
+
+::ndk::ScopedAStatus StaIface::reconnect()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::reconnectInternal);
+}
+
+::ndk::ScopedAStatus StaIface::disconnect()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::disconnectInternal);
+}
+
+::ndk::ScopedAStatus StaIface::setPowerSave(
+ bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setPowerSaveInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaIface::initiateTdlsDiscover(
+ const std::vector<uint8_t>& in_macAddress)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::initiateTdlsDiscoverInternal, in_macAddress);
+}
+
+::ndk::ScopedAStatus StaIface::initiateTdlsSetup(
+ const std::vector<uint8_t>& in_macAddress)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::initiateTdlsSetupInternal, in_macAddress);
+}
+
+::ndk::ScopedAStatus StaIface::initiateTdlsTeardown(
+ const std::vector<uint8_t>& in_macAddress)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::initiateTdlsTeardownInternal, in_macAddress);
+}
+
+::ndk::ScopedAStatus StaIface::initiateAnqpQuery(
+ const std::vector<uint8_t>& in_macAddress,
+ const std::vector<AnqpInfoId>& in_infoElements,
+ const std::vector<Hs20AnqpSubtypes>& in_subTypes)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::initiateAnqpQueryInternal, in_macAddress,
+ in_infoElements, in_subTypes);
+}
+
+::ndk::ScopedAStatus StaIface::initiateVenueUrlAnqpQuery(
+ const std::vector<uint8_t>& in_macAddress)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::initiateVenueUrlAnqpQueryInternal, in_macAddress);
+}
+
+::ndk::ScopedAStatus StaIface::initiateHs20IconQuery(
+ const std::vector<uint8_t>& in_macAddress,
+ const std::string& in_fileName)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::initiateHs20IconQueryInternal, in_macAddress,
+ in_fileName);
+}
+
+::ndk::ScopedAStatus StaIface::getMacAddress(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::getMacAddressInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::startRxFilter()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::startRxFilterInternal);
+}
+
+::ndk::ScopedAStatus StaIface::stopRxFilter()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::stopRxFilterInternal);
+}
+
+::ndk::ScopedAStatus StaIface::addRxFilter(
+ RxFilterType in_type)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::addRxFilterInternal, in_type);
+}
+
+::ndk::ScopedAStatus StaIface::removeRxFilter(
+ RxFilterType in_type)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::removeRxFilterInternal, in_type);
+}
+
+::ndk::ScopedAStatus StaIface::setBtCoexistenceMode(
+ BtCoexistenceMode in_mode)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setBtCoexistenceModeInternal, in_mode);
+}
+
+::ndk::ScopedAStatus StaIface::setBtCoexistenceScanModeEnabled(
+ bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setBtCoexistenceScanModeEnabledInternal,
+ in_enable);
+}
+
+::ndk::ScopedAStatus StaIface::setSuspendModeEnabled(
+ bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setSuspendModeEnabledInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaIface::setCountryCode(
+ const std::vector<uint8_t>& in_code)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setCountryCodeInternal, in_code);
+}
+
+::ndk::ScopedAStatus StaIface::startWpsRegistrar(
+ const std::vector<uint8_t>& in_bssid,
+ const std::string& in_pin)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::startWpsRegistrarInternal, in_bssid, in_pin);
+}
+
+::ndk::ScopedAStatus StaIface::startWpsPbc(
+ const std::vector<uint8_t>& in_bssid)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::startWpsPbcInternal, in_bssid);
+}
+
+::ndk::ScopedAStatus StaIface::startWpsPinKeypad(
+ const std::string& in_pin)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::startWpsPinKeypadInternal, in_pin);
+}
+
+::ndk::ScopedAStatus StaIface::startWpsPinDisplay(
+ const std::vector<uint8_t>& in_bssid,
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::startWpsPinDisplayInternal, _aidl_return, in_bssid);
+}
+
+::ndk::ScopedAStatus StaIface::cancelWps()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::cancelWpsInternal);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsDeviceName(
+ const std::string& in_name)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setWpsDeviceNameInternal, in_name);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsDeviceType(
+ const std::vector<uint8_t>& in_type)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setWpsDeviceTypeInternal, in_type);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsManufacturer(
+ const std::string& in_manufacturer)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setWpsManufacturerInternal, in_manufacturer);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsModelName(
+ const std::string& in_modelName)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setWpsModelNameInternal, in_modelName);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsModelNumber(
+ const std::string& in_modelNumber)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setWpsModelNumberInternal, in_modelNumber);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsSerialNumber(
+ const std::string& in_serialNumber)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setWpsSerialNumberInternal, in_serialNumber);
+}
+
+::ndk::ScopedAStatus StaIface::setWpsConfigMethods(
+ WpsConfigMethods in_configMethods)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setWpsConfigMethodsInternal, in_configMethods);
+}
+
+::ndk::ScopedAStatus StaIface::setExternalSim(
+ bool in_useExternalSim)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::setExternalSimInternal, in_useExternalSim);
+}
+
+::ndk::ScopedAStatus StaIface::addExtRadioWork(
+ const std::string& in_name, int32_t in_freqInMhz,
+ int32_t in_timeoutInSec,
+ int32_t* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::addExtRadioWorkInternal, _aidl_return, in_name, in_freqInMhz,
+ in_timeoutInSec);
+}
+
+::ndk::ScopedAStatus StaIface::removeExtRadioWork(
+ int32_t in_id)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::removeExtRadioWorkInternal, in_id);
+}
+
+::ndk::ScopedAStatus StaIface::enableAutoReconnect(
+ bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::enableAutoReconnectInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaIface::getKeyMgmtCapabilities(
+ KeyMgmtMask* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaIface::getKeyMgmtCapabilitiesInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::addDppPeerUri(
+ const std::string& in_uri, int32_t* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaIface::addDppPeerUriInternal, _aidl_return, in_uri);
+}
+
+::ndk::ScopedAStatus StaIface::removeDppUri(
+ int32_t in_id)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaIface::removeDppUriInternal, in_id);
+}
+
+::ndk::ScopedAStatus StaIface::startDppConfiguratorInitiator(
+ int32_t in_peerBootstrapId, int32_t in_ownBootstrapId,
+ const std::string& in_ssid, const std::string& in_password,
+ const std::string& in_psk, DppNetRole in_netRole,
+ DppAkm in_securityAkm)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaIface::startDppConfiguratorInitiatorInternal,
+ in_peerBootstrapId,in_ownBootstrapId, in_ssid, in_password,
+ in_psk, in_netRole, in_securityAkm);
+}
+
+::ndk::ScopedAStatus StaIface::startDppEnrolleeInitiator(
+ int32_t in_peerBootstrapId, int32_t in_ownBootstrapId)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaIface::startDppEnrolleeInitiatorInternal, in_peerBootstrapId,
+ in_ownBootstrapId);
+}
+
+::ndk::ScopedAStatus StaIface::stopDppInitiator()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaIface::stopDppInitiatorInternal);
+}
+
+::ndk::ScopedAStatus StaIface::getConnectionCapabilities(
+ ConnectionCapabilities* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_UNKNOWN,
+ &StaIface::getConnectionCapabilitiesInternal,
+ _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::generateDppBootstrapInfoForResponder(
+ const std::vector<uint8_t>& in_macAddress, const std::string& in_deviceInfo,
+ DppCurve in_curve, DppResponderBootstrapInfo* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::generateDppBootstrapInfoForResponderInternal, _aidl_return,
+ in_macAddress, in_deviceInfo, in_curve);
+}
+
+::ndk::ScopedAStatus StaIface::startDppEnrolleeResponder(
+ int32_t in_listenChannel)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::startDppEnrolleeResponderInternal, in_listenChannel);
+}
+
+::ndk::ScopedAStatus StaIface::stopDppResponder(
+ int32_t in_ownBootstrapId)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &StaIface::stopDppResponderInternal, in_ownBootstrapId);
+}
+
+::ndk::ScopedAStatus StaIface::getWpaDriverCapabilities(
+ WpaDriverCapabilitiesMask* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_UNKNOWN,
+ &StaIface::getWpaDriverCapabilitiesInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaIface::setMboCellularDataStatus(
+ bool in_available)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_UNKNOWN,
+ &StaIface::setMboCellularDataStatusInternal, in_available);
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaIface::getNameInternal()
+{
+ return {ifname_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<IfaceType, ndk::ScopedAStatus> StaIface::getTypeInternal()
+{
+ return {IfaceType::STA, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::filsHlpFlushRequestInternal()
+{
+#ifdef CONFIG_FILS
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+
+ wpas_flush_fils_hlp_req(wpa_s);
+ return ndk::ScopedAStatus::ok();
+#else /* CONFIG_FILS */
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN, "");
+#endif /* CONFIG_FILS */
+}
+
+ndk::ScopedAStatus StaIface::filsHlpAddRequestInternal(
+ const std::vector<uint8_t> &dst_mac, const std::vector<uint8_t> &pkt)
+{
+#ifdef CONFIG_FILS
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ struct fils_hlp_req *req;
+
+ if (!pkt.size())
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ if (dst_mac.size() != ETH_ALEN)
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+
+
+ req = (struct fils_hlp_req *)os_zalloc(sizeof(*req));
+ if (!req)
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+
+ os_memcpy(req->dst, dst_mac.data(), ETH_ALEN);
+
+ req->pkt = wpabuf_alloc_copy(pkt.data(), pkt.size());
+ if (!req->pkt) {
+ os_free(req);
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+
+ dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
+ return ndk::ScopedAStatus::ok();
+#else /* CONFIG_FILS */
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#endif /* CONFIG_FILS */
+}
+
+std::pair<std::shared_ptr<ISupplicantStaNetwork>, ndk::ScopedAStatus>
+StaIface::addNetworkInternal()
+{
+ std::shared_ptr<ISupplicantStaNetwork> network;
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ struct wpa_ssid *ssid = wpa_supplicant_add_network(wpa_s);
+ if (!ssid) {
+ return {network, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager ||
+ aidl_manager->getStaNetworkAidlObjectByIfnameAndNetworkId(
+ wpa_s->ifname, ssid->id, &network)) {
+ return {network, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {network, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::removeNetworkInternal(int32_t id)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ int result = wpa_supplicant_remove_network(wpa_s, id);
+ if (result == -1) {
+ return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
+ }
+ if (result != 0) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::shared_ptr<ISupplicantStaNetwork>, ndk::ScopedAStatus>
+StaIface::getNetworkInternal(int32_t id)
+{
+ std::shared_ptr<ISupplicantStaNetwork> network;
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (!ssid) {
+ return {network, createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN)};
+ }
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager ||
+ aidl_manager->getStaNetworkAidlObjectByIfnameAndNetworkId(
+ wpa_s->ifname, ssid->id, &network)) {
+ return {network, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {network, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<int32_t>, ndk::ScopedAStatus>
+StaIface::listNetworksInternal()
+{
+ std::vector<int32_t> network_ids;
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ for (struct wpa_ssid *wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
+ wpa_ssid = wpa_ssid->next) {
+ network_ids.emplace_back(wpa_ssid->id);
+ }
+ return {std::move(network_ids), ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::registerCallbackInternal(
+ const std::shared_ptr<ISupplicantStaIfaceCallback> &callback)
+{
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager ||
+ aidl_manager->addStaIfaceCallbackAidlObject(ifname_, callback)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::reassociateInternal()
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+ }
+ wpas_request_connection(wpa_s);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::reconnectInternal()
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+ }
+ if (!wpa_s->disconnected) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_NOT_DISCONNECTED);
+ }
+ wpas_request_connection(wpa_s);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::disconnectInternal()
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+ }
+ wpas_request_disconnection(wpa_s);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::setPowerSaveInternal(bool enable)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+ }
+ if (wpa_drv_set_p2p_powersave(wpa_s, enable, -1, -1)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::initiateTdlsDiscoverInternal(
+ const std::vector<uint8_t> &mac_address)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ int ret;
+ const u8 *peer = mac_address.data();
+ if (wpa_tdls_is_external_setup(wpa_s->wpa)) {
+ ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
+ } else {
+ ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
+ }
+ if (ret) {
+ wpa_printf(MSG_INFO, "StaIface: TDLS discover failed: %d", ret);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::initiateTdlsSetupInternal(
+ const std::vector<uint8_t> &mac_address)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ int ret;
+ const u8 *peer = mac_address.data();
+ if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
+ !(wpa_s->conf->tdls_external_control)) {
+ wpa_tdls_remove(wpa_s->wpa, peer);
+ ret = wpa_tdls_start(wpa_s->wpa, peer);
+ } else {
+ ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
+ }
+ if (ret) {
+ wpa_printf(MSG_INFO, "StaIface: TDLS setup failed: %d", ret);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::initiateTdlsTeardownInternal(
+ const std::vector<uint8_t> &mac_address)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ int ret;
+ const u8 *peer = mac_address.data();
+ if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
+ !(wpa_s->conf->tdls_external_control)) {
+ ret = wpa_tdls_teardown_link(
+ wpa_s->wpa, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
+ } else {
+ ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
+ }
+ if (ret) {
+ wpa_printf(MSG_INFO, "StaIface: TDLS teardown failed: %d", ret);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::initiateAnqpQueryInternal(
+ const std::vector<uint8_t> &mac_address,
+ const std::vector<AnqpInfoId> &info_elements,
+ const std::vector<Hs20AnqpSubtypes> &sub_types)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (info_elements.size() > kMaxAnqpElems) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ uint16_t info_elems_buf[kMaxAnqpElems];
+ uint32_t num_info_elems = 0;
+ for (const auto &info_element : info_elements) {
+ info_elems_buf[num_info_elems++] =
+ static_cast<std::underlying_type<
+ AnqpInfoId>::type>(info_element);
+ }
+ uint32_t sub_types_bitmask = 0;
+ for (const auto &type : sub_types) {
+ sub_types_bitmask |= BIT(
+ static_cast<std::underlying_type<
+ Hs20AnqpSubtypes>::type>(type));
+ }
+
+ if (anqp_send_req(
+ wpa_s, mac_address.data(), 0, info_elems_buf, num_info_elems,
+ sub_types_bitmask, 0)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::initiateVenueUrlAnqpQueryInternal(
+ const std::vector<uint8_t> &mac_address)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ uint16_t info_elems_buf[1] = {ANQP_VENUE_URL};
+
+ if (anqp_send_req(
+ wpa_s, mac_address.data(), 0, info_elems_buf, 1, 0, 0)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::initiateHs20IconQueryInternal(
+ const std::vector<uint8_t> &mac_address, const std::string &file_name)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ wpa_s->fetch_osu_icon_in_progress = 0;
+ if (hs20_anqp_send_req(
+ wpa_s, mac_address.data(), BIT(HS20_STYPE_ICON_REQUEST),
+ reinterpret_cast<const uint8_t *>(file_name.c_str()),
+ file_name.size(), true)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaIface::getMacAddressInternal()
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ std::vector<char> cmd(
+ kGetMacAddress, kGetMacAddress + sizeof(kGetMacAddress));
+ char driver_cmd_reply_buf[4096] = {};
+ int ret = wpa_drv_driver_cmd(
+ wpa_s, cmd.data(), driver_cmd_reply_buf,
+ sizeof(driver_cmd_reply_buf));
+ // Reply is of the format: "Macaddr = XX:XX:XX:XX:XX:XX"
+ std::string reply_str = driver_cmd_reply_buf;
+ if (ret < 0 || reply_str.empty() ||
+ reply_str.find("=") == std::string::npos) {
+ return {std::vector<uint8_t>(),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ // Remove all whitespace first and then split using the delimiter "=".
+ reply_str.erase(
+ remove_if(reply_str.begin(), reply_str.end(), isspace),
+ reply_str.end());
+ std::string mac_addr_str =
+ reply_str.substr(reply_str.find("=") + 1, reply_str.size());
+ std::vector<uint8_t> mac_addr(6);
+ if (hwaddr_aton(mac_addr_str.c_str(), mac_addr.data())) {
+ return {std::vector<uint8_t>(),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {mac_addr, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::startRxFilterInternal()
+{
+ return doZeroArgDriverCommand(retrieveIfacePtr(), kStartRxFilter);
+}
+
+ndk::ScopedAStatus StaIface::stopRxFilterInternal()
+{
+ return doZeroArgDriverCommand(retrieveIfacePtr(), kStopRxFilter);
+}
+
+ndk::ScopedAStatus StaIface::addRxFilterInternal(
+ RxFilterType type)
+{
+ return doOneArgDriverCommand(
+ retrieveIfacePtr(), kAddRxFilter,
+ convertAidlRxFilterTypeToInternal(type));
+}
+
+ndk::ScopedAStatus StaIface::removeRxFilterInternal(
+ RxFilterType type)
+{
+ return doOneArgDriverCommand(
+ retrieveIfacePtr(), kRemoveRxFilter,
+ convertAidlRxFilterTypeToInternal(type));
+}
+
+ndk::ScopedAStatus StaIface::setBtCoexistenceModeInternal(
+ BtCoexistenceMode mode)
+{
+ return doOneArgDriverCommand(
+ retrieveIfacePtr(), kSetBtCoexistenceMode,
+ convertAidlBtCoexModeToInternal(mode));
+}
+
+ndk::ScopedAStatus StaIface::setBtCoexistenceScanModeEnabledInternal(bool enable)
+{
+ const char *cmd;
+ if (enable) {
+ cmd = kSetBtCoexistenceScanStart;
+ } else {
+ cmd = kSetBtCoexistenceScanStop;
+ }
+ return doZeroArgDriverCommand(retrieveIfacePtr(), cmd);
+}
+
+ndk::ScopedAStatus StaIface::setSuspendModeEnabledInternal(bool enable)
+{
+ const char *cmd;
+ if (enable) {
+ cmd = kSetSupendModeEnabled;
+ } else {
+ cmd = kSetSupendModeDisabled;
+ }
+ return doZeroArgDriverCommand(retrieveIfacePtr(), cmd);
+}
+
+ndk::ScopedAStatus StaIface::setCountryCodeInternal(
+ const std::vector<uint8_t> &code)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ ndk::ScopedAStatus status = doOneArgDriverCommand(
+ wpa_s, kSetCountryCode,
+ std::string(std::begin(code), std::end(code)));
+ if (!status.isOk()) {
+ return status;
+ }
+ struct p2p_data *p2p = wpa_s->global->p2p;
+ if (p2p) {
+ char country[3];
+ country[0] = code[0];
+ country[1] = code[1];
+ country[2] = 0x04;
+ p2p_set_country(p2p, country);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::startWpsRegistrarInternal(
+ const std::vector<uint8_t> &bssid, const std::string &pin)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (wpas_wps_start_reg(wpa_s, bssid.data(), pin.c_str(), nullptr)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::startWpsPbcInternal(
+ const std::vector<uint8_t> &bssid)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ const uint8_t *bssid_addr =
+ is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+ if (wpas_wps_start_pbc(wpa_s, bssid_addr, 0, 0)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::startWpsPinKeypadInternal(const std::string &pin)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (wpas_wps_start_pin(
+ wpa_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaIface::startWpsPinDisplayInternal(
+ const std::vector<uint8_t> &bssid)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ const uint8_t *bssid_addr =
+ is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+ int pin =
+ wpas_wps_start_pin(wpa_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
+ if (pin < 0) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::convertWpsPinToString(pin),
+ ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::cancelWpsInternal()
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (wpas_wps_cancel(wpa_s)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::setWpsDeviceNameInternal(const std::string &name)
+{
+ return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
+}
+
+ndk::ScopedAStatus StaIface::setWpsDeviceTypeInternal(
+ const std::vector<uint8_t> &type)
+{
+ std::array<uint8_t, 8> type_arr;
+ std::copy_n(type.begin(), 8, type_arr.begin());
+ return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type_arr);
+}
+
+ndk::ScopedAStatus StaIface::setWpsManufacturerInternal(
+ const std::string &manufacturer)
+{
+ return iface_config_utils::setWpsManufacturer(
+ retrieveIfacePtr(), manufacturer);
+}
+
+ndk::ScopedAStatus StaIface::setWpsModelNameInternal(
+ const std::string &model_name)
+{
+ return iface_config_utils::setWpsModelName(
+ retrieveIfacePtr(), model_name);
+}
+
+ndk::ScopedAStatus StaIface::setWpsModelNumberInternal(
+ const std::string &model_number)
+{
+ return iface_config_utils::setWpsModelNumber(
+ retrieveIfacePtr(), model_number);
+}
+
+ndk::ScopedAStatus StaIface::setWpsSerialNumberInternal(
+ const std::string &serial_number)
+{
+ return iface_config_utils::setWpsSerialNumber(
+ retrieveIfacePtr(), serial_number);
+}
+
+ndk::ScopedAStatus StaIface::setWpsConfigMethodsInternal(WpsConfigMethods config_methods)
+{
+ return iface_config_utils::setWpsConfigMethods(
+ retrieveIfacePtr(), static_cast<uint16_t>(config_methods));
+}
+
+ndk::ScopedAStatus StaIface::setExternalSimInternal(bool useExternalSim)
+{
+ return iface_config_utils::setExternalSim(
+ retrieveIfacePtr(), useExternalSim);
+}
+
+std::pair<uint32_t, ndk::ScopedAStatus> StaIface::addExtRadioWorkInternal(
+ const std::string &name, uint32_t freq_in_mhz, uint32_t timeout_in_sec)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ auto *ework = static_cast<struct wpa_external_work *>(
+ os_zalloc(sizeof(struct wpa_external_work)));
+ if (!ework) {
+ return {UINT32_MAX, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+
+ std::string radio_work_name = kExtRadioWorkNamePrefix + name;
+ os_strlcpy(ework->type, radio_work_name.c_str(), sizeof(ework->type));
+ ework->timeout = timeout_in_sec;
+ wpa_s->ext_work_id++;
+ if (wpa_s->ext_work_id == 0) {
+ wpa_s->ext_work_id++;
+ }
+ ework->id = wpa_s->ext_work_id;
+
+ if (radio_add_work(
+ wpa_s, freq_in_mhz, ework->type, 0, extRadioWorkStartCb,
+ ework)) {
+ os_free(ework);
+ return {UINT32_MAX, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {ework->id, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::removeExtRadioWorkInternal(uint32_t id)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ struct wpa_radio_work *work;
+ dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
+ {
+ if (os_strncmp(
+ work->type, kExtRadioWorkNamePrefix,
+ sizeof(kExtRadioWorkNamePrefix)) != 0)
+ continue;
+
+ auto *ework =
+ static_cast<struct wpa_external_work *>(work->ctx);
+ if (ework->id != id)
+ continue;
+
+ wpa_dbg(
+ wpa_s, MSG_DEBUG, "Completed external radio work %u (%s)",
+ ework->id, ework->type);
+ eloop_cancel_timeout(extRadioWorkTimeoutCb, work, NULL);
+ endExtRadioWork(work);
+
+ return ndk::ScopedAStatus::ok();
+ }
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+}
+
+ndk::ScopedAStatus StaIface::enableAutoReconnectInternal(bool enable)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ wpa_s->auto_reconnect_disabled = enable ? 0 : 1;
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<uint32_t, ndk::ScopedAStatus>
+StaIface::addDppPeerUriInternal(const std::string& uri)
+{
+#ifdef CONFIG_DPP
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ int32_t id;
+
+ id = wpas_dpp_qr_code(wpa_s, uri.c_str());
+
+ if (id > 0) {
+ return {id, ndk::ScopedAStatus::ok()};
+ }
+#endif
+ return {-1, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+}
+
+ndk::ScopedAStatus StaIface::removeDppUriInternal(uint32_t bootstrap_id)
+{
+#ifdef CONFIG_DPP
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ std::string bootstrap_id_str;
+
+ if (bootstrap_id == 0) {
+ bootstrap_id_str = "*";
+ }
+ else {
+ bootstrap_id_str = std::to_string(bootstrap_id);
+ }
+
+ if (dpp_bootstrap_remove(wpa_s->dpp, bootstrap_id_str.c_str()) >= 0) {
+ return ndk::ScopedAStatus::ok();
+ }
+#endif
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+}
+
+ndk::ScopedAStatus StaIface::startDppConfiguratorInitiatorInternal(
+ uint32_t peer_bootstrap_id, uint32_t own_bootstrap_id,
+ const std::string& ssid, const std::string& password,
+ const std::string& psk, DppNetRole net_role, DppAkm security_akm)
+{
+#ifdef CONFIG_DPP
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ std::string cmd = "";
+
+ if (net_role != DppNetRole::AP &&
+ net_role != DppNetRole::STA) {
+ wpa_printf(MSG_ERROR,
+ "DPP: Error: Invalid network role specified: %d", net_role);
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+
+ cmd += " peer=" + std::to_string(peer_bootstrap_id);
+ cmd += (own_bootstrap_id > 0) ?
+ " own=" + std::to_string(own_bootstrap_id) : "";
+
+ /* Check for supported AKMs */
+ if (security_akm != DppAkm::PSK && security_akm != DppAkm::SAE &&
+ security_akm != DppAkm::PSK_SAE) {
+ wpa_printf(MSG_ERROR, "DPP: Error: invalid AKM specified: %d",
+ security_akm);
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+
+ /* SAE AKM requires SSID and password to be initialized */
+ if ((security_akm == DppAkm::SAE ||
+ security_akm == DppAkm::PSK_SAE) &&
+ (ssid.empty() || password.empty())) {
+ wpa_printf(MSG_ERROR, "DPP: Error: Password or SSID not specified");
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ } else if (security_akm == DppAkm::PSK ||
+ security_akm == DppAkm::PSK_SAE) {
+ /* PSK AKM requires SSID and password/psk to be initialized */
+ if (ssid.empty()) {
+ wpa_printf(MSG_ERROR, "DPP: Error: SSID not specified");
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ if (password.empty() && psk.empty()) {
+ wpa_printf(MSG_ERROR, "DPP: Error: Password or PSK not specified");
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ }
+
+ cmd += " role=configurator";
+ cmd += (ssid.empty()) ? "" : " ssid=" + ssid;
+
+ if (!psk.empty()) {
+ cmd += " psk=" + psk;
+ } else {
+ cmd += (password.empty()) ? "" : " pass=" + password;
+ }
+
+ std::string role = "";
+ if (net_role == DppNetRole::AP) {
+ role = "ap-";
+ }
+ else {
+ role = "sta-";
+ }
+
+ switch (security_akm) {
+ case DppAkm::PSK:
+ role += "psk";
+ break;
+
+ case DppAkm::SAE:
+ role += "sae";
+ break;
+
+ case DppAkm::PSK_SAE:
+ role += "psk-sae";
+ break;
+
+ default:
+ wpa_printf(MSG_ERROR,
+ "DPP: Invalid or unsupported security AKM specified: %d", security_akm);
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+
+ cmd += " conf=";
+ cmd += role;
+
+ if (net_role == DppNetRole::STA) {
+ /* DPP R2 connection status request */
+ cmd += " conn_status=1";
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "DPP initiator command: %s", cmd.c_str());
+
+ if (wpas_dpp_auth_init(wpa_s, cmd.c_str()) == 0) {
+ return ndk::ScopedAStatus::ok();
+ }
+#endif
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+}
+
+ndk::ScopedAStatus StaIface::startDppEnrolleeInitiatorInternal(
+ uint32_t peer_bootstrap_id, uint32_t own_bootstrap_id) {
+#ifdef CONFIG_DPP
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ std::string cmd = "";
+
+ /* Report received configuration to AIDL and create an internal profile */
+ wpa_s->conf->dpp_config_processing = 1;
+
+ cmd += " peer=" + std::to_string(peer_bootstrap_id);
+ cmd += (own_bootstrap_id > 0) ?
+ " own=" + std::to_string(own_bootstrap_id) : "";
+
+ cmd += " role=enrollee";
+
+ wpa_printf(MSG_DEBUG,
+ "DPP initiator command: %s", cmd.c_str());
+
+ if (wpas_dpp_auth_init(wpa_s, cmd.c_str()) == 0) {
+ return ndk::ScopedAStatus::ok();
+ }
+#endif
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+}
+ndk::ScopedAStatus StaIface::stopDppInitiatorInternal()
+{
+#ifdef CONFIG_DPP
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+
+ wpas_dpp_stop(wpa_s);
+ return ndk::ScopedAStatus::ok();
+#else
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#endif
+}
+
+std::pair<DppResponderBootstrapInfo, ndk::ScopedAStatus>
+StaIface::generateDppBootstrapInfoForResponderInternal(
+ const std::vector<uint8_t> &mac_address,
+ const std::string& device_info, DppCurve curve)
+{
+#ifdef CONFIG_DPP
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ std::string cmd = "type=qrcode";
+ int32_t id;
+ int32_t listen_channel = 0;
+ DppResponderBootstrapInfo bootstrap_info;
+ const char *uri;
+ std::string listen_channel_str;
+ std::string mac_addr_str;
+ char buf[3] = {0};
+
+ cmd += (device_info.empty()) ? "" : " info=" + device_info;
+
+ listen_channel_str = getDppListenChannel(wpa_s, &listen_channel);
+ if (listen_channel == 0) {
+ wpa_printf(MSG_ERROR, "StaIface: Failed to derive DPP listen channel");
+ return {bootstrap_info, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ cmd += " chan=" + listen_channel_str;
+
+ cmd += " mac=";
+ for (int i = 0;i < 6;i++) {
+ snprintf(buf, sizeof(buf), "%02x", mac_address[i]);
+ mac_addr_str.append(buf);
+ }
+ cmd += mac_addr_str;
+
+ cmd += " curve=" + convertCurveTypeToName(curve);
+
+ id = dpp_bootstrap_gen(wpa_s->dpp, cmd.c_str());
+ wpa_printf(MSG_DEBUG,
+ "DPP generate bootstrap QR code command: %s id: %d", cmd.c_str(), id);
+ if (id > 0) {
+ uri = dpp_bootstrap_get_uri(wpa_s->dpp, id);
+ if (uri) {
+ wpa_printf(MSG_DEBUG, "DPP Bootstrap info: id: %d "
+ "listen_channel: %d uri: %s", id, listen_channel, uri);
+ bootstrap_info.bootstrapId = id;
+ bootstrap_info.listenChannel = listen_channel;
+ bootstrap_info.uri = uri;
+ return {bootstrap_info, ndk::ScopedAStatus::ok()};
+ }
+ }
+ return {bootstrap_info, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+#else
+ return {bootstrap_info, createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED)};
+#endif
+}
+
+ndk::ScopedAStatus StaIface::startDppEnrolleeResponderInternal(uint32_t listen_channel)
+{
+#ifdef CONFIG_DPP
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ std::string cmd = "";
+ uint32_t freq = (listen_channel <= 14 ? 2407 : 5000) + listen_channel * 5;
+
+ /* Report received configuration to AIDL and create an internal profile */
+ wpa_s->conf->dpp_config_processing = 1;
+
+ cmd += std::to_string(freq);
+ cmd += " role=enrollee netrole=sta";
+
+ wpa_printf(MSG_DEBUG,
+ "DPP Enrollee Responder command: %s", cmd.c_str());
+
+ if (wpas_dpp_listen(wpa_s, cmd.c_str()) == 0) {
+ return ndk::ScopedAStatus::ok();
+ }
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#else
+ return createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED);
+#endif
+}
+
+ndk::ScopedAStatus StaIface::stopDppResponderInternal(uint32_t own_bootstrap_id)
+{
+#ifdef CONFIG_DPP
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ std::string bootstrap_id_str;
+
+ if (own_bootstrap_id == 0) {
+ bootstrap_id_str = "*";
+ }
+ else {
+ bootstrap_id_str = std::to_string(own_bootstrap_id);
+ }
+
+ wpa_printf(MSG_DEBUG, "DPP Stop DPP Responder id: %d ", own_bootstrap_id);
+ wpas_dpp_stop(wpa_s);
+ wpas_dpp_listen_stop(wpa_s);
+
+ if (dpp_bootstrap_remove(wpa_s->dpp, bootstrap_id_str.c_str()) < 0) {
+ wpa_printf(MSG_ERROR, "StaIface: dpp_bootstrap_remove failed");
+ }
+
+ return ndk::ScopedAStatus::ok();
+#else
+ return createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED);
+#endif
+}
+
+std::pair<ConnectionCapabilities, ndk::ScopedAStatus>
+StaIface::getConnectionCapabilitiesInternal()
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ ConnectionCapabilities capa;
+
+ if (wpa_s->connection_set) {
+ capa.legacyMode = LegacyMode::UNKNOWN;
+ if (wpa_s->connection_he) {
+ capa.technology = WifiTechnology::HE;
+ } else if (wpa_s->connection_vht) {
+ capa.technology = WifiTechnology::VHT;
+ } else if (wpa_s->connection_ht) {
+ capa.technology = WifiTechnology::HT;
+ } else {
+ capa.technology = WifiTechnology::LEGACY;
+ if (wpas_freq_to_band(wpa_s->assoc_freq) == BAND_2_4_GHZ) {
+ capa.legacyMode = (wpa_s->connection_11b_only) ? LegacyMode::B_MODE
+ : LegacyMode::G_MODE;
+ } else {
+ capa.legacyMode = LegacyMode::A_MODE;
+ }
+ }
+ switch (wpa_s->connection_channel_bandwidth) {
+ case CHAN_WIDTH_20:
+ capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
+ break;
+ case CHAN_WIDTH_40:
+ capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_40;
+ break;
+ case CHAN_WIDTH_80:
+ capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_80;
+ break;
+ case CHAN_WIDTH_160:
+ capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_160;
+ break;
+ case CHAN_WIDTH_80P80:
+ capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_80P80;
+ break;
+ default:
+ capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
+ break;
+ }
+ capa.maxNumberRxSpatialStreams = wpa_s->connection_max_nss_rx;
+ capa.maxNumberTxSpatialStreams = wpa_s->connection_max_nss_tx;
+ } else {
+ capa.technology = WifiTechnology::UNKNOWN;
+ capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
+ capa.maxNumberTxSpatialStreams = 1;
+ capa.maxNumberRxSpatialStreams = 1;
+ capa.legacyMode = LegacyMode::UNKNOWN;
+ }
+ return {capa, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<WpaDriverCapabilitiesMask, ndk::ScopedAStatus>
+StaIface::getWpaDriverCapabilitiesInternal()
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ uint32_t mask = 0;
+
+#ifdef CONFIG_MBO
+ /* MBO has no capability flags. It's mainly legacy 802.11v BSS
+ * transition + Cellular steering. 11v is a default feature in
+ * supplicant. And cellular steering is handled in framework.
+ */
+ mask |= static_cast<uint32_t>(WpaDriverCapabilitiesMask::MBO);
+ if (wpa_s->enable_oce & OCE_STA) {
+ mask |= static_cast<uint32_t>(WpaDriverCapabilitiesMask::OCE);
+ }
+#endif
+#ifdef CONFIG_SAE_PK
+ mask |= static_cast<uint32_t>(WpaDriverCapabilitiesMask::SAE_PK);
+#endif
+ mask |= static_cast<uint32_t>(WpaDriverCapabilitiesMask::WFD_R2);
+
+ wpa_printf(MSG_DEBUG, "Driver capability mask: 0x%x", mask);
+
+ return {static_cast<WpaDriverCapabilitiesMask>(mask),
+ ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaIface::setMboCellularDataStatusInternal(bool available)
+{
+#ifdef CONFIG_MBO
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ enum mbo_cellular_capa mbo_cell_capa;
+
+ if (available) {
+ mbo_cell_capa = MBO_CELL_CAPA_AVAILABLE;
+ } else {
+ mbo_cell_capa = MBO_CELL_CAPA_NOT_AVAILABLE;
+ }
+
+#ifdef ENABLE_PRIV_CMD_UPDATE_MBO_CELL_STATUS
+ char mbo_cmd[32];
+ char buf[32];
+
+ os_snprintf(mbo_cmd, sizeof(mbo_cmd), "%s %d", "MBO CELL_DATA_CAP", mbo_cell_capa);
+ if (wpa_drv_driver_cmd(wpa_s, mbo_cmd, buf, sizeof(buf)) < 0) {
+ wpa_printf(MSG_ERROR, "MBO CELL_DATA_CAP cmd failed CAP:%d", mbo_cell_capa);
+ }
+#else
+ wpas_mbo_update_cell_capa(wpa_s, mbo_cell_capa);
+#endif
+
+ return ndk::ScopedAStatus::ok();
+#else
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#endif
+}
+
+std::pair<KeyMgmtMask, ndk::ScopedAStatus>
+StaIface::getKeyMgmtCapabilitiesInternal()
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ struct wpa_driver_capa capa;
+
+ /* Get capabilities from driver and populate the key management mask */
+ if (wpa_drv_get_capa(wpa_s, &capa) < 0) {
+ return {static_cast<KeyMgmtMask>(0),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+
+ return {convertWpaKeyMgmtCapabilitiesToAidl(wpa_s, &capa),
+ ndk::ScopedAStatus::ok()};
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this iface.
+ * If the underlying iface is removed, then all RPC method calls on this object
+ * will return failure.
+ */
+wpa_supplicant *StaIface::retrieveIfacePtr()
+{
+ return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
+}
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wpa_supplicant/aidl/sta_iface.h b/wpa_supplicant/aidl/sta_iface.h
new file mode 100644
index 0000000..98c3187
--- /dev/null
+++ b/wpa_supplicant/aidl/sta_iface.h
@@ -0,0 +1,263 @@
+/*
+ * WPA Supplicant - Sta Iface Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_STA_IFACE_H
+#define WPA_SUPPLICANT_AIDL_STA_IFACE_H
+
+#include <array>
+#include <vector>
+
+#include <android-base/macros.h>
+
+#include <aidl/android/hardware/wifi/supplicant/AnqpInfoId.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantStaIface.h>
+#include <aidl/android/hardware/wifi/supplicant/BtCoexistenceMode.h>
+#include <aidl/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.h>
+#include <aidl/android/hardware/wifi/supplicant/RxFilterType.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+#include "config.h"
+#include "driver_i.h"
+#include "wpa.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+/**
+ * Implementation of StaIface aidl object. Each unique aidl
+ * object is used for control operations on a specific interface
+ * controlled by wpa_supplicant.
+ */
+class StaIface : public BnSupplicantStaIface
+{
+public:
+ StaIface(struct wpa_global* wpa_global, const char ifname[]);
+ ~StaIface() override = default;
+ // AIDL does not provide a built-in mechanism to let the server
+ // invalidate a AIDL interface object after creation. If any client
+ // process holds onto a reference to the object in their context,
+ // any method calls on that reference will continue to be directed to
+ // the server.
+ // However Supplicant HAL needs to control the lifetime of these
+ // objects. So, add a public |invalidate| method to all |Iface| and
+ // |Network| objects.
+ // This will be used to mark an object invalid when the corresponding
+ // iface or network is removed.
+ // All AIDL method implementations should check if the object is still
+ // marked valid before processing them.
+ void invalidate();
+ bool isValid();
+
+ // Aidl methods exposed.
+ ::ndk::ScopedAStatus getName(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getType(IfaceType* _aidl_return) override;
+ ::ndk::ScopedAStatus addNetwork(
+ std::shared_ptr<ISupplicantStaNetwork>* _aidl_return) override;
+ ::ndk::ScopedAStatus removeNetwork(int32_t in_id) override;
+ ::ndk::ScopedAStatus filsHlpFlushRequest() override;
+ ::ndk::ScopedAStatus filsHlpAddRequest(
+ const std::vector<uint8_t>& in_dst_mac,
+ const std::vector<uint8_t>& in_pkt) override;
+ ::ndk::ScopedAStatus getNetwork(
+ int32_t in_id, std::shared_ptr<ISupplicantStaNetwork>* _aidl_return) override;
+ ::ndk::ScopedAStatus listNetworks(std::vector<int32_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus registerCallback(
+ const std::shared_ptr<ISupplicantStaIfaceCallback>& in_callback) override;
+ ::ndk::ScopedAStatus reassociate() override;
+ ::ndk::ScopedAStatus reconnect() override;
+ ::ndk::ScopedAStatus disconnect() override;
+ ::ndk::ScopedAStatus setPowerSave(bool in_enable) override;
+ ::ndk::ScopedAStatus initiateTdlsDiscover(
+ const std::vector<uint8_t>& in_macAddress) override;
+ ::ndk::ScopedAStatus initiateTdlsSetup(
+ const std::vector<uint8_t>& in_macAddress) override;
+ ::ndk::ScopedAStatus initiateTdlsTeardown(
+ const std::vector<uint8_t>& in_macAddress) override;
+ ::ndk::ScopedAStatus initiateAnqpQuery(
+ const std::vector<uint8_t>& in_macAddress,
+ const std::vector<AnqpInfoId>& in_infoElements,
+ const std::vector<Hs20AnqpSubtypes>& in_subTypes) override;
+ ::ndk::ScopedAStatus initiateVenueUrlAnqpQuery(
+ const std::vector<uint8_t>& in_macAddress) override;
+ ::ndk::ScopedAStatus initiateHs20IconQuery(
+ const std::vector<uint8_t>& in_macAddress, const std::string& in_fileName) override;
+ ::ndk::ScopedAStatus getMacAddress(std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus startRxFilter() override;
+ ::ndk::ScopedAStatus stopRxFilter() override;
+ ::ndk::ScopedAStatus addRxFilter(RxFilterType in_type) override;
+ ::ndk::ScopedAStatus removeRxFilter(RxFilterType in_type) override;
+ ::ndk::ScopedAStatus setBtCoexistenceMode(BtCoexistenceMode in_mode) override;
+ ::ndk::ScopedAStatus setBtCoexistenceScanModeEnabled(bool in_enable) override;
+ ::ndk::ScopedAStatus setSuspendModeEnabled(bool in_enable) override;
+ ::ndk::ScopedAStatus setCountryCode(const std::vector<uint8_t>& in_code) override;
+ ::ndk::ScopedAStatus startWpsRegistrar(
+ const std::vector<uint8_t>& in_bssid, const std::string& in_pin) override;
+ ::ndk::ScopedAStatus startWpsPbc(const std::vector<uint8_t>& in_bssid) override;
+ ::ndk::ScopedAStatus startWpsPinDisplay(
+ const std::vector<uint8_t>& in_bssid, std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus startWpsPinKeypad(const std::string& in_pin) override;
+ ::ndk::ScopedAStatus cancelWps() override;
+ ::ndk::ScopedAStatus setWpsDeviceName(const std::string& in_name) override;
+ ::ndk::ScopedAStatus setWpsDeviceType(const std::vector<uint8_t>& in_type) override;
+ ::ndk::ScopedAStatus setWpsManufacturer(const std::string& in_manufacturer) override;
+ ::ndk::ScopedAStatus setWpsModelName(const std::string& in_modelName) override;
+ ::ndk::ScopedAStatus setWpsModelNumber(const std::string& in_modelNumber) override;
+ ::ndk::ScopedAStatus setWpsSerialNumber(const std::string& in_serialNumber) override;
+ ::ndk::ScopedAStatus setWpsConfigMethods(WpsConfigMethods in_configMethods) override;
+ ::ndk::ScopedAStatus setExternalSim(bool in_useExternalSim) override;
+ ::ndk::ScopedAStatus addExtRadioWork(
+ const std::string& in_name, int32_t in_freqInMhz,
+ int32_t in_timeoutInSec, int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus removeExtRadioWork(int32_t in_id) override;
+ ::ndk::ScopedAStatus enableAutoReconnect(bool in_enable) override;
+ ::ndk::ScopedAStatus getKeyMgmtCapabilities(KeyMgmtMask* _aidl_return) override;
+ ::ndk::ScopedAStatus addDppPeerUri(
+ const std::string& in_uri, int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus removeDppUri(int32_t in_id) override;
+ ::ndk::ScopedAStatus startDppConfiguratorInitiator(
+ int32_t in_peerBootstrapId, int32_t in_ownBootstrapId,
+ const std::string& in_ssid, const std::string& in_password,
+ const std::string& in_psk, DppNetRole in_netRole, DppAkm in_securityAkm) override;
+ ::ndk::ScopedAStatus startDppEnrolleeInitiator(
+ int32_t in_peerBootstrapId, int32_t in_ownBootstrapId) override;
+ ::ndk::ScopedAStatus stopDppInitiator() override;
+ ::ndk::ScopedAStatus getConnectionCapabilities(ConnectionCapabilities* _aidl_return) override;
+ ::ndk::ScopedAStatus getWpaDriverCapabilities(WpaDriverCapabilitiesMask* _aidl_return) override;
+ ::ndk::ScopedAStatus setMboCellularDataStatus(bool in_available) override;
+ ::ndk::ScopedAStatus generateDppBootstrapInfoForResponder(
+ const std::vector<uint8_t>& in_macAddress,
+ const std::string& in_deviceInfo, DppCurve in_curve,
+ DppResponderBootstrapInfo* _aidl_return) override;
+ ::ndk::ScopedAStatus startDppEnrolleeResponder(int32_t in_listenChannel) override;
+ ::ndk::ScopedAStatus stopDppResponder(int32_t in_ownBootstrapId) override;
+
+private:
+ // Corresponding worker functions for the AIDL methods.
+ std::pair<std::string, ndk::ScopedAStatus> getNameInternal();
+ std::pair<IfaceType, ndk::ScopedAStatus> getTypeInternal();
+ std::pair<std::shared_ptr<ISupplicantStaNetwork>, ndk::ScopedAStatus>
+ addNetworkInternal();
+ ndk::ScopedAStatus filsHlpFlushRequestInternal();
+ ndk::ScopedAStatus filsHlpAddRequestInternal(
+ const std::vector<uint8_t>& dst_mac,
+ const std::vector<uint8_t>& pkt);
+ ndk::ScopedAStatus removeNetworkInternal(int32_t id);
+ std::pair<std::shared_ptr<ISupplicantStaNetwork>, ndk::ScopedAStatus>
+ getNetworkInternal(int32_t id);
+ std::pair<std::vector<int32_t>, ndk::ScopedAStatus>
+ listNetworksInternal();
+ ndk::ScopedAStatus registerCallbackInternal(
+ const std::shared_ptr<ISupplicantStaIfaceCallback>& callback);
+ ndk::ScopedAStatus reassociateInternal();
+ ndk::ScopedAStatus reconnectInternal();
+ ndk::ScopedAStatus disconnectInternal();
+ ndk::ScopedAStatus setPowerSaveInternal(bool enable);
+ ndk::ScopedAStatus initiateTdlsDiscoverInternal(
+ const std::vector<uint8_t>& mac_address);
+ ndk::ScopedAStatus initiateTdlsSetupInternal(
+ const std::vector<uint8_t>& mac_address);
+ ndk::ScopedAStatus initiateTdlsTeardownInternal(
+ const std::vector<uint8_t>& mac_address);
+ ndk::ScopedAStatus initiateAnqpQueryInternal(
+ const std::vector<uint8_t>& mac_address,
+ const std::vector<AnqpInfoId>& info_elements,
+ const std::vector<Hs20AnqpSubtypes>&
+ sub_types);
+ ndk::ScopedAStatus initiateVenueUrlAnqpQueryInternal(
+ const std::vector<uint8_t>& mac_address);
+ ndk::ScopedAStatus initiateHs20IconQueryInternal(
+ const std::vector<uint8_t>& mac_address,
+ const std::string& file_name);
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+ getMacAddressInternal();
+ ndk::ScopedAStatus startRxFilterInternal();
+ ndk::ScopedAStatus stopRxFilterInternal();
+ ndk::ScopedAStatus addRxFilterInternal(
+ RxFilterType type);
+ ndk::ScopedAStatus removeRxFilterInternal(
+ RxFilterType type);
+ ndk::ScopedAStatus setBtCoexistenceModeInternal(
+ BtCoexistenceMode mode);
+ ndk::ScopedAStatus setBtCoexistenceScanModeEnabledInternal(bool enable);
+ ndk::ScopedAStatus setSuspendModeEnabledInternal(bool enable);
+ ndk::ScopedAStatus setCountryCodeInternal(
+ const std::vector<uint8_t>& code);
+ ndk::ScopedAStatus startWpsRegistrarInternal(
+ const std::vector<uint8_t>& bssid, const std::string& pin);
+ ndk::ScopedAStatus startWpsPbcInternal(
+ const std::vector<uint8_t>& bssid);
+ ndk::ScopedAStatus startWpsPinKeypadInternal(const std::string& pin);
+ std::pair<std::string, ndk::ScopedAStatus> startWpsPinDisplayInternal(
+ const std::vector<uint8_t>& bssid);
+ ndk::ScopedAStatus cancelWpsInternal();
+ ndk::ScopedAStatus setWpsDeviceNameInternal(const std::string& name);
+ ndk::ScopedAStatus setWpsDeviceTypeInternal(
+ const std::vector<uint8_t>& type);
+ ndk::ScopedAStatus setWpsManufacturerInternal(
+ const std::string& manufacturer);
+ ndk::ScopedAStatus setWpsModelNameInternal(const std::string& model_name);
+ ndk::ScopedAStatus setWpsModelNumberInternal(
+ const std::string& model_number);
+ ndk::ScopedAStatus setWpsSerialNumberInternal(
+ const std::string& serial_number);
+ ndk::ScopedAStatus setWpsConfigMethodsInternal(WpsConfigMethods config_methods);
+ ndk::ScopedAStatus setExternalSimInternal(bool useExternalSim);
+ std::pair<uint32_t, ndk::ScopedAStatus> addExtRadioWorkInternal(
+ const std::string& name, uint32_t freq_in_mhz,
+ uint32_t timeout_in_sec);
+ ndk::ScopedAStatus removeExtRadioWorkInternal(uint32_t id);
+ ndk::ScopedAStatus enableAutoReconnectInternal(bool enable);
+ std::pair<KeyMgmtMask, ndk::ScopedAStatus> getKeyMgmtCapabilitiesInternal();
+ std::pair<uint32_t, ndk::ScopedAStatus> addDppPeerUriInternal(const std::string& uri);
+ ndk::ScopedAStatus removeDppUriInternal(uint32_t bootstrap_id);
+ ndk::ScopedAStatus startDppConfiguratorInitiatorInternal(uint32_t peer_bootstrap_id,
+ uint32_t own_bootstrap_id,
+ const std::string& ssid, const std::string& password,
+ const std::string& psk, DppNetRole net_role, DppAkm security_akm);
+ ndk::ScopedAStatus startDppEnrolleeInitiatorInternal(uint32_t peer_bootstrap_id,
+ uint32_t own_bootstrap_id);
+ ndk::ScopedAStatus stopDppInitiatorInternal();
+ std::pair<ConnectionCapabilities, ndk::ScopedAStatus> getConnectionCapabilitiesInternal();
+ std::pair<WpaDriverCapabilitiesMask, ndk::ScopedAStatus> getWpaDriverCapabilitiesInternal();
+ ndk::ScopedAStatus setMboCellularDataStatusInternal(bool available);
+ std::pair<DppResponderBootstrapInfo, ndk::ScopedAStatus>
+ generateDppBootstrapInfoForResponderInternal(
+ const std::vector<uint8_t>& mac_address, const std::string& device_info,
+ DppCurve curve);
+ ndk::ScopedAStatus startDppEnrolleeResponderInternal(uint32_t listen_channel);
+ ndk::ScopedAStatus stopDppResponderInternal(uint32_t own_bootstrap_id);
+
+ struct wpa_supplicant* retrieveIfacePtr();
+
+ // Reference to the global wpa_struct. This is assumed to be valid for
+ // the lifetime of the process.
+ struct wpa_global* wpa_global_;
+ // Name of the iface this aidl object controls
+ const std::string ifname_;
+ bool is_valid_;
+
+ DISALLOW_COPY_AND_ASSIGN(StaIface);
+};
+
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WPA_SUPPLICANT_AIDL_STA_IFACE_H
diff --git a/wpa_supplicant/aidl/sta_network.cpp b/wpa_supplicant/aidl/sta_network.cpp
new file mode 100644
index 0000000..b6294da
--- /dev/null
+++ b/wpa_supplicant/aidl/sta_network.cpp
@@ -0,0 +1,2461 @@
+/*
+ * WPA Supplicant - Sta network Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "aidl_manager.h"
+#include "aidl_return_util.h"
+#include "misc_utils.h"
+#include "sta_network.h"
+
+extern "C"
+{
+#include "wps_supplicant.h"
+}
+
+namespace {
+using aidl::android::hardware::wifi::supplicant::AuthAlgMask;
+using aidl::android::hardware::wifi::supplicant::EapMethod;
+using aidl::android::hardware::wifi::supplicant::EapPhase2Method;
+using aidl::android::hardware::wifi::supplicant::GroupCipherMask;
+using aidl::android::hardware::wifi::supplicant::GroupMgmtCipherMask;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaNetwork;
+using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
+using aidl::android::hardware::wifi::supplicant::PairwiseCipherMask;
+using aidl::android::hardware::wifi::supplicant::ProtoMask;
+
+constexpr uint8_t kZeroBssid[6] = {0, 0, 0, 0, 0, 0};
+
+constexpr uint32_t kAllowedKeyMgmtMask =
+ (static_cast<uint32_t>(KeyMgmtMask::NONE) |
+ static_cast<uint32_t>(KeyMgmtMask::WPA_PSK) |
+ static_cast<uint32_t>(KeyMgmtMask::WPA_EAP) |
+ static_cast<uint32_t>(KeyMgmtMask::IEEE8021X) |
+ static_cast<uint32_t>(KeyMgmtMask::FT_EAP) |
+ static_cast<uint32_t>(KeyMgmtMask::FT_PSK) |
+ static_cast<uint32_t>(KeyMgmtMask::OSEN) |
+ static_cast<uint32_t>(KeyMgmtMask::SAE) |
+ static_cast<uint32_t>(KeyMgmtMask::SUITE_B_192) |
+ static_cast<uint32_t>(KeyMgmtMask::OWE) |
+ static_cast<uint32_t>(KeyMgmtMask::WPA_PSK_SHA256) |
+ static_cast<uint32_t>(KeyMgmtMask::WPA_EAP_SHA256) |
+ static_cast<uint32_t>(KeyMgmtMask::WAPI_PSK) |
+ static_cast<uint32_t>(KeyMgmtMask::WAPI_CERT) |
+ static_cast<uint32_t>(KeyMgmtMask::FILS_SHA256) |
+ static_cast<uint32_t>(KeyMgmtMask::FILS_SHA384));
+constexpr uint32_t kAllowedProtoMask =
+ (static_cast<uint32_t>(ProtoMask::WPA) |
+ static_cast<uint32_t>(ProtoMask::RSN) |
+ static_cast<uint32_t>(ProtoMask::OSEN) |
+ static_cast<uint32_t>(ProtoMask::WAPI));
+constexpr uint32_t kAllowedAuthAlgMask =
+ (static_cast<uint32_t>(AuthAlgMask::OPEN) |
+ static_cast<uint32_t>(AuthAlgMask::SHARED) |
+ static_cast<uint32_t>(AuthAlgMask::LEAP) |
+ static_cast<uint32_t>(AuthAlgMask::SAE));
+constexpr uint32_t kAllowedGroupCipherMask =
+ (static_cast<uint32_t>(GroupCipherMask::WEP40) |
+ static_cast<uint32_t>(GroupCipherMask::WEP104) |
+ static_cast<uint32_t>(GroupCipherMask::TKIP) |
+ static_cast<uint32_t>(GroupCipherMask::CCMP) |
+ static_cast<uint32_t>(
+ GroupCipherMask::GTK_NOT_USED) |
+ static_cast<uint32_t>(GroupCipherMask::GCMP_256) |
+ static_cast<uint32_t>(GroupCipherMask::SMS4) |
+ static_cast<uint32_t>(GroupCipherMask::GCMP_128));
+constexpr uint32_t kAllowedPairwisewCipherMask =
+ (static_cast<uint32_t>(PairwiseCipherMask::NONE) |
+ static_cast<uint32_t>(PairwiseCipherMask::TKIP) |
+ static_cast<uint32_t>(PairwiseCipherMask::CCMP) |
+ static_cast<uint32_t>(
+ PairwiseCipherMask::GCMP_256) |
+ static_cast<uint32_t>(
+ PairwiseCipherMask::SMS4) |
+ static_cast<uint32_t>(PairwiseCipherMask::GCMP_128));
+constexpr uint32_t kAllowedGroupMgmtCipherMask =
+ (static_cast<uint32_t>(
+ GroupMgmtCipherMask::BIP_GMAC_128) |
+ static_cast<uint32_t>(
+ GroupMgmtCipherMask::BIP_GMAC_256) |
+ static_cast<uint32_t>(
+ GroupMgmtCipherMask::BIP_CMAC_256));
+
+constexpr uint32_t kEapMethodMax =
+ static_cast<uint32_t>(EapMethod::WFA_UNAUTH_TLS) + 1;
+constexpr char const *kEapMethodStrings[kEapMethodMax] = {
+ "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA", "AKA'", "WFA-UNAUTH-TLS"};
+constexpr uint32_t kEapPhase2MethodMax =
+ static_cast<uint32_t>(EapPhase2Method::AKA_PRIME) + 1;
+constexpr char const *kEapPhase2MethodStrings[kEapPhase2MethodMax] = {
+ "", "PAP", "MSCHAP", "MSCHAPV2", "GTC", "SIM", "AKA", "AKA'"};
+constexpr char kEapPhase2AuthPrefix[] = "auth=";
+constexpr char kEapPhase2AuthEapPrefix[] = "autheap=";
+constexpr char kNetworkEapSimGsmAuthResponse[] = "GSM-AUTH";
+constexpr char kNetworkEapSimUmtsAuthResponse[] = "UMTS-AUTH";
+constexpr char kNetworkEapSimUmtsAutsResponse[] = "UMTS-AUTS";
+constexpr char kNetworkEapSimGsmAuthFailure[] = "GSM-FAIL";
+constexpr char kNetworkEapSimUmtsAuthFailure[] = "UMTS-FAIL";
+
+#ifdef CONFIG_WAPI_INTERFACE
+std::string dummyWapiCertSuite;
+std::vector<uint8_t> dummyWapiPsk;
+#endif /* CONFIG_WAPI_INTERFACE */
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+using aidl_return_util::validateAndCall;
+using misc_utils::createStatus;
+using misc_utils::createStatusWithMsg;
+
+StaNetwork::StaNetwork(
+ struct wpa_global *wpa_global, const char ifname[], int network_id)
+ : wpa_global_(wpa_global),
+ ifname_(ifname),
+ network_id_(network_id),
+ is_valid_(true)
+{}
+
+void StaNetwork::invalidate() { is_valid_ = false; }
+bool StaNetwork::isValid()
+{
+ return (is_valid_ && (retrieveNetworkPtr() != nullptr));
+}
+
+::ndk::ScopedAStatus StaNetwork::getId(
+ int32_t* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getIdInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getInterfaceName(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getInterfaceNameInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getType(
+ IfaceType* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getTypeInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::registerCallback(
+ const std::shared_ptr<ISupplicantStaNetworkCallback>& in_callback)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::registerCallbackInternal, in_callback);
+}
+
+::ndk::ScopedAStatus StaNetwork::setSsid(
+ const std::vector<uint8_t>& in_ssid)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setSsidInternal, in_ssid);
+}
+
+::ndk::ScopedAStatus StaNetwork::setBssid(
+ const std::vector<uint8_t>& in_bssid)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setBssidInternal, in_bssid);
+}
+
+::ndk::ScopedAStatus StaNetwork::setScanSsid(bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setScanSsidInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::setKeyMgmt(
+ KeyMgmtMask in_keyMgmtMask)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setKeyMgmtInternal, in_keyMgmtMask);
+}
+
+::ndk::ScopedAStatus StaNetwork::setProto(
+ ProtoMask in_protoMask)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setProtoInternal, in_protoMask);
+}
+
+::ndk::ScopedAStatus StaNetwork::setAuthAlg(
+ AuthAlgMask in_authAlgMask)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setAuthAlgInternal, in_authAlgMask);
+}
+
+::ndk::ScopedAStatus StaNetwork::setGroupCipher(
+ GroupCipherMask in_groupCipherMask)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setGroupCipherInternal, in_groupCipherMask);
+}
+
+::ndk::ScopedAStatus StaNetwork::setPairwiseCipher(
+ PairwiseCipherMask in_pairwiseCipherMask)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setPairwiseCipherInternal,
+ in_pairwiseCipherMask);
+}
+
+::ndk::ScopedAStatus StaNetwork::setPskPassphrase(
+ const std::string& in_psk)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setPskPassphraseInternal, in_psk);
+}
+
+::ndk::ScopedAStatus StaNetwork::setPsk(
+ const std::vector<uint8_t>& in_psk)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setPskInternal, in_psk);
+}
+
+::ndk::ScopedAStatus StaNetwork::setWepKey(
+ int32_t in_keyIdx, const std::vector<uint8_t>& in_wepKey)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setWepKeyInternal, in_keyIdx, in_wepKey);
+}
+
+::ndk::ScopedAStatus StaNetwork::setWepTxKeyIdx(
+ int32_t in_keyIdx)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setWepTxKeyIdxInternal, in_keyIdx);
+}
+
+::ndk::ScopedAStatus StaNetwork::setRequirePmf(bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setRequirePmfInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapMethod(
+ EapMethod in_method)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapMethodInternal, in_method);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapPhase2Method(
+ EapPhase2Method in_method)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapPhase2MethodInternal, in_method);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapIdentity(
+ const std::vector<uint8_t>& in_identity)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapIdentityInternal, in_identity);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapEncryptedImsiIdentity(
+ const std::vector<uint8_t>& in_identity)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapEncryptedImsiIdentityInternal,
+ in_identity);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapAnonymousIdentity(
+ const std::vector<uint8_t>& in_identity)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapAnonymousIdentityInternal, in_identity);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapPassword(
+ const std::vector<uint8_t>& in_password)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapPasswordInternal, in_password);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapCACert(
+ const std::string& in_path)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapCACertInternal, in_path);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapCAPath(
+ const std::string& in_path)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapCAPathInternal, in_path);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapClientCert(
+ const std::string& in_path)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapClientCertInternal, in_path);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapPrivateKeyId(
+ const std::string& in_id)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapPrivateKeyIdInternal, in_id);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapSubjectMatch(
+ const std::string& in_match)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapSubjectMatchInternal, in_match);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapAltSubjectMatch(
+ const std::string& in_match)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapAltSubjectMatchInternal, in_match);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapEngine(bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapEngineInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapEngineID(
+ const std::string& in_id)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapEngineIDInternal, in_id);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapDomainSuffixMatch(
+ const std::string& in_match)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapDomainSuffixMatchInternal, in_match);
+}
+
+::ndk::ScopedAStatus StaNetwork::setProactiveKeyCaching(
+ bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setProactiveKeyCachingInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::setIdStr(
+ const std::string& in_idStr)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setIdStrInternal, in_idStr);
+}
+
+::ndk::ScopedAStatus StaNetwork::setUpdateIdentifier(
+ int32_t in_id)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setUpdateIdentifierInternal, in_id);
+}
+
+::ndk::ScopedAStatus StaNetwork::setWapiCertSuite(
+ const std::string& in_suite)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setWapiCertSuiteInternal, in_suite);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEdmg(bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEdmgInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::getSsid(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getSsidInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus StaNetwork::getBssid(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getBssidInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getScanSsid(
+ bool* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getScanSsidInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getKeyMgmt(
+ KeyMgmtMask* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getKeyMgmtInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getProto(
+ ProtoMask* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getProtoInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getAuthAlg(
+ AuthAlgMask* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getAuthAlgInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getGroupCipher(
+ GroupCipherMask* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getGroupCipherInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getPairwiseCipher(
+ PairwiseCipherMask* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getPairwiseCipherInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getPskPassphrase(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getPskPassphraseInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getPsk(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getPskInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getSaePassword(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getSaePasswordInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getSaePasswordId(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getSaePasswordIdInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getWepKey(
+ int32_t in_keyIdx,
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getWepKeyInternal, _aidl_return, in_keyIdx);
+}
+
+::ndk::ScopedAStatus StaNetwork::getWepTxKeyIdx(
+ int32_t* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getWepTxKeyIdxInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getRequirePmf(
+ bool* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getRequirePmfInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapMethod(
+ EapMethod* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapMethodInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapPhase2Method(
+ EapPhase2Method* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapPhase2MethodInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapIdentity(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapIdentityInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapAnonymousIdentity(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapAnonymousIdentityInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapPassword(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapPasswordInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapCACert(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapCACertInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapCAPath(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapCAPathInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapClientCert(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapClientCertInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapPrivateKeyId(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapPrivateKeyIdInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapSubjectMatch(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapSubjectMatchInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapAltSubjectMatch(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapAltSubjectMatchInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapEngine(
+ bool* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapEngineInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapEngineId(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapEngineIdInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEapDomainSuffixMatch(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEapDomainSuffixMatchInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getIdStr(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getIdStrInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getWpsNfcConfigurationToken(
+ std::vector<uint8_t>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getWpsNfcConfigurationTokenInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getWapiCertSuite(
+ std::string* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getWapiCertSuiteInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::getEdmg(
+ bool* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getEdmgInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::enable(bool in_noConnect)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::enableInternal, in_noConnect);
+}
+
+::ndk::ScopedAStatus StaNetwork::disable()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::disableInternal);
+}
+
+::ndk::ScopedAStatus StaNetwork::select()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::selectInternal);
+}
+
+::ndk::ScopedAStatus StaNetwork::sendNetworkEapSimGsmAuthResponse(
+ const std::vector<NetworkResponseEapSimGsmAuthParams>& in_params)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::sendNetworkEapSimGsmAuthResponseInternal,
+ in_params);
+}
+
+::ndk::ScopedAStatus StaNetwork::sendNetworkEapSimGsmAuthFailure()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::sendNetworkEapSimGsmAuthFailureInternal);
+}
+
+::ndk::ScopedAStatus StaNetwork::sendNetworkEapSimUmtsAuthResponse(
+ const NetworkResponseEapSimUmtsAuthParams& in_params)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::sendNetworkEapSimUmtsAuthResponseInternal,
+ in_params);
+}
+
+::ndk::ScopedAStatus StaNetwork::sendNetworkEapSimUmtsAutsResponse(
+ const std::vector<uint8_t>& in_auts)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::sendNetworkEapSimUmtsAutsResponseInternal,
+ in_auts);
+}
+
+::ndk::ScopedAStatus StaNetwork::sendNetworkEapSimUmtsAuthFailure()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::sendNetworkEapSimUmtsAuthFailureInternal);
+}
+
+::ndk::ScopedAStatus StaNetwork::sendNetworkEapIdentityResponse(
+ const std::vector<uint8_t>& in_identity,
+ const std::vector<uint8_t>& in_encryptedIdentity)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::sendNetworkEapIdentityResponseInternal,
+ in_identity, in_encryptedIdentity);
+}
+
+::ndk::ScopedAStatus StaNetwork::setGroupMgmtCipher(
+ GroupMgmtCipherMask in_groupMgmtCipherMask)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setGroupMgmtCipherInternal,
+ in_groupMgmtCipherMask);
+}
+
+::ndk::ScopedAStatus StaNetwork::getGroupMgmtCipher(
+ GroupMgmtCipherMask* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getGroupMgmtCipherInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::enableTlsSuiteBEapPhase1Param(
+ bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::enableTlsSuiteBEapPhase1ParamInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::enableSuiteBEapOpenSslCiphers()
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::enableSuiteBEapOpenSslCiphersInternal);
+}
+
+::ndk::ScopedAStatus StaNetwork::setSaePassword(
+ const std::string& in_saePassword)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setSaePasswordInternal, in_saePassword);
+}
+
+::ndk::ScopedAStatus StaNetwork::setSaePasswordId(
+ const std::string& in_saePasswordId)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setSaePasswordIdInternal, in_saePasswordId);
+}
+
+::ndk::ScopedAStatus StaNetwork::setOcsp(
+ OcspType in_ocspType)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setOcspInternal, in_ocspType);
+}
+
+::ndk::ScopedAStatus StaNetwork::getOcsp(
+ OcspType* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::getOcspInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus StaNetwork::setPmkCache(
+ const std::vector<uint8_t>& in_serializedEntry)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setPmkCacheInternal, in_serializedEntry);
+}
+
+::ndk::ScopedAStatus StaNetwork::setEapErp(
+ bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setEapErpInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaNetwork::setSaeH2eMode(
+ SaeH2eMode in_mode)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::setSaeH2eModeInternal, in_mode);
+}
+
+::ndk::ScopedAStatus StaNetwork::enableSaePkOnlyMode(
+ bool in_enable)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+ &StaNetwork::enableSaePkOnlyModeInternal, in_enable);
+}
+
+std::pair<uint32_t, ndk::ScopedAStatus> StaNetwork::getIdInternal()
+{
+ return {network_id_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getInterfaceNameInternal()
+{
+ return {ifname_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<IfaceType, ndk::ScopedAStatus> StaNetwork::getTypeInternal()
+{
+ return {IfaceType::STA, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::registerCallbackInternal(
+ const std::shared_ptr<ISupplicantStaNetworkCallback> &callback)
+{
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager || aidl_manager->addStaNetworkCallbackAidlObject(
+ ifname_, network_id_, callback)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setSsidInternal(const std::vector<uint8_t> &ssid)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (ssid.size() == 0 ||
+ ssid.size() >
+ static_cast<uint32_t>(ISupplicantStaNetwork::
+ SSID_MAX_LEN_IN_BYTES)) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ if (setByteArrayFieldAndResetState(
+ ssid.data(), ssid.size(), &(wpa_ssid->ssid),
+ &(wpa_ssid->ssid_len), "ssid")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ if (wpa_ssid->passphrase) {
+ wpa_config_update_psk(wpa_ssid);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setBssidInternal(
+ const std::vector<uint8_t> &bssid)
+{
+ if (bssid.size() != ETH_ALEN) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ int prev_bssid_set = wpa_ssid->bssid_set;
+ u8 prev_bssid[ETH_ALEN];
+ os_memcpy(prev_bssid, wpa_ssid->bssid, ETH_ALEN);
+ // Zero'ed array is used to clear out the BSSID value.
+ if (os_memcmp(bssid.data(), kZeroBssid, ETH_ALEN) == 0) {
+ wpa_ssid->bssid_set = 0;
+ wpa_printf(MSG_MSGDUMP, "BSSID any");
+ } else {
+ os_memcpy(wpa_ssid->bssid, bssid.data(), ETH_ALEN);
+ wpa_ssid->bssid_set = 1;
+ wpa_hexdump(MSG_MSGDUMP, "BSSID", wpa_ssid->bssid, ETH_ALEN);
+ }
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if ((wpa_ssid->bssid_set != prev_bssid_set ||
+ os_memcmp(wpa_ssid->bssid, prev_bssid, ETH_ALEN) != 0)) {
+ wpas_notify_network_bssid_set_changed(wpa_s, wpa_ssid);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setScanSsidInternal(bool enable)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ wpa_ssid->scan_ssid = enable ? 1 : 0;
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setAuthAlgInternal(
+ AuthAlgMask mask)
+{
+ uint32_t auth_alg_mask = static_cast<uint32_t>(mask);
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (auth_alg_mask & ~kAllowedAuthAlgMask) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ wpa_ssid->auth_alg = auth_alg_mask;
+ wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", wpa_ssid->auth_alg);
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEdmgInternal(bool enable)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ wpa_ssid->enable_edmg = enable ? 1 : 0;
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setPskPassphraseInternal(const std::string &rawPsk)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ std::string psk = rawPsk;
+#ifdef CONFIG_WAPI_INTERFACE
+ if (wpa_ssid->key_mgmt & WPA_KEY_MGMT_WAPI_PSK) {
+ if (rawPsk.size() > 2 && rawPsk.front()== '"' && rawPsk.back() == '"') {
+ psk = rawPsk.substr(1, rawPsk.size() - 2);
+ } else {
+ if ((rawPsk.size() & 1)) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ size_t len = psk.size() / 2;
+ uint8_t *buf = (uint8_t *) os_malloc(len);
+ if (hexstr2bin(psk.c_str(), buf, len) < 0) {
+ os_free(buf);
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ std::vector<uint8_t> bytes(buf, buf + len);
+ os_free(buf);
+ return setWapiPskInternal(bytes);
+ }
+ }
+#endif
+ if (isPskPassphraseValid(psk)) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ if (wpa_ssid->passphrase &&
+ os_strlen(wpa_ssid->passphrase) == psk.size() &&
+ os_memcmp(wpa_ssid->passphrase, psk.c_str(), psk.size()) == 0) {
+ return ndk::ScopedAStatus::ok();
+ }
+ // Flag to indicate if raw psk is calculated or not using
+ // |wpa_config_update_psk|. Deferred if ssid not already set.
+ wpa_ssid->psk_set = 0;
+ if (setStringKeyFieldAndResetState(
+ psk.c_str(), &(wpa_ssid->passphrase), "psk passphrase")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ if (wpa_ssid->ssid_len) {
+ wpa_config_update_psk(wpa_ssid);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setPskInternal(const std::vector<uint8_t> &psk)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ WPA_ASSERT(psk.size() == sizeof(wpa_ssid->psk));
+ str_clear_free(wpa_ssid->passphrase);
+ wpa_ssid->passphrase = nullptr;
+ os_memcpy(wpa_ssid->psk, psk.data(), sizeof(wpa_ssid->psk));
+ wpa_ssid->psk_set = 1;
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setWepKeyInternal(
+ uint32_t key_idx, const std::vector<uint8_t> &wep_key)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (key_idx >=
+ static_cast<uint32_t>(
+ ISupplicantStaNetwork::WEP_KEYS_MAX_NUM)) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ if (wep_key.size() !=
+ static_cast<uint32_t>(ISupplicantStaNetwork::
+ WEP40_KEY_LEN_IN_BYTES) &&
+ wep_key.size() !=
+ static_cast<uint32_t>(ISupplicantStaNetwork::
+ WEP104_KEY_LEN_IN_BYTES)) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ os_memcpy(wpa_ssid->wep_key[key_idx], wep_key.data(), wep_key.size());
+ wpa_ssid->wep_key_len[key_idx] = wep_key.size();
+ std::string msg_dump_title("wep_key" + std::to_string(key_idx));
+ wpa_hexdump_key(
+ MSG_MSGDUMP, msg_dump_title.c_str(), wpa_ssid->wep_key[key_idx],
+ wpa_ssid->wep_key_len[key_idx]);
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setWepTxKeyIdxInternal(uint32_t key_idx)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (key_idx >=
+ static_cast<uint32_t>(
+ ISupplicantStaNetwork::WEP_KEYS_MAX_NUM)) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ wpa_ssid->wep_tx_keyidx = key_idx;
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setRequirePmfInternal(bool enable)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (enable) {
+ wpa_ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+ }
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapMethodInternal(
+ EapMethod method)
+{
+ uint32_t eap_method_idx = static_cast<
+ std::underlying_type<EapMethod>::type>(
+ method);
+ if (eap_method_idx >= kEapMethodMax) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ int retrieved_vendor, retrieved_method;
+ const char *method_str = kEapMethodStrings[eap_method_idx];
+ // This string lookup is needed to check if the device supports the
+ // corresponding EAP type.
+ retrieved_method = eap_peer_get_type(method_str, &retrieved_vendor);
+ if (retrieved_vendor == EAP_VENDOR_IETF &&
+ retrieved_method == EAP_TYPE_NONE) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ if (wpa_ssid->eap.eap_methods) {
+ os_free(wpa_ssid->eap.eap_methods);
+ }
+ // wpa_supplicant can support setting multiple eap methods for each
+ // network. But, this is not really used by Android. So, just adding
+ // support for setting one EAP method for each network. The additional
+ // |eap_method_type| member in the array is used to indicate the end
+ // of list.
+ wpa_ssid->eap.eap_methods =
+ (eap_method_type *)os_malloc(sizeof(eap_method_type) * 2);
+ if (!wpa_ssid->eap.eap_methods) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ wpa_ssid->eap.eap_methods[0].vendor = retrieved_vendor;
+ wpa_ssid->eap.eap_methods[0].method = retrieved_method;
+ wpa_ssid->eap.eap_methods[1].vendor = EAP_VENDOR_IETF;
+ wpa_ssid->eap.eap_methods[1].method = EAP_TYPE_NONE;
+
+ wpa_ssid->leap = 0;
+ wpa_ssid->non_leap = 0;
+ if (retrieved_vendor == EAP_VENDOR_IETF &&
+ retrieved_method == EAP_TYPE_LEAP) {
+ wpa_ssid->leap++;
+ } else {
+ wpa_ssid->non_leap++;
+ }
+ wpa_hexdump(
+ MSG_MSGDUMP, "eap methods", (u8 *)wpa_ssid->eap.eap_methods,
+ sizeof(eap_method_type) * 2);
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapPhase2MethodInternal(
+ EapPhase2Method method)
+{
+ uint32_t eap_phase2_method_idx = static_cast<
+ std::underlying_type<EapPhase2Method>::type>(
+ method);
+ if (eap_phase2_method_idx >= kEapPhase2MethodMax) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ // EAP method needs to be set for us to construct the eap
+ // phase 2 method string.
+ ndk::ScopedAStatus status;
+ EapMethod eap_method;
+ std::tie(eap_method, status) = getEapMethodInternal();
+ if (!status.isOk()) {
+ return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+ "EAP method not set");
+ }
+ std::string eap_phase2_str;
+ if (method == EapPhase2Method::NONE) {
+ eap_phase2_str = "";
+ } else if (
+ eap_method == EapMethod::TTLS &&
+ method == EapPhase2Method::GTC) {
+ eap_phase2_str = kEapPhase2AuthEapPrefix;
+ } else {
+ eap_phase2_str = kEapPhase2AuthPrefix;
+ }
+ eap_phase2_str += kEapPhase2MethodStrings[eap_phase2_method_idx];
+ if (setStringFieldAndResetState(
+ eap_phase2_str.c_str(), &(wpa_ssid->eap.phase2),
+ "eap phase2")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapIdentityInternal(
+ const std::vector<uint8_t> &identity)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (setByteArrayFieldAndResetState(
+ identity.data(), identity.size(), &(wpa_ssid->eap.identity),
+ &(wpa_ssid->eap.identity_len), "eap identity")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ // plain IMSI identity
+ if (setByteArrayFieldAndResetState(
+ identity.data(), identity.size(),
+ &(wpa_ssid->eap.imsi_identity),
+ &(wpa_ssid->eap.imsi_identity_len), "eap imsi identity")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapEncryptedImsiIdentityInternal(
+ const std::vector<uint8_t> &identity)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ // encrypted IMSI identity
+ if (setByteArrayFieldAndResetState(
+ identity.data(), identity.size(), &(wpa_ssid->eap.identity),
+ &(wpa_ssid->eap.identity_len), "eap encrypted imsi identity")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapAnonymousIdentityInternal(
+ const std::vector<uint8_t> &identity)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (setByteArrayFieldAndResetState(
+ identity.data(), identity.size(),
+ &(wpa_ssid->eap.anonymous_identity),
+ &(wpa_ssid->eap.anonymous_identity_len),
+ "eap anonymous_identity")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapPasswordInternal(
+ const std::vector<uint8_t> &password)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (setByteArrayKeyFieldAndResetState(
+ password.data(), password.size(), &(wpa_ssid->eap.password),
+ &(wpa_ssid->eap.password_len), "eap password")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ wpa_ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
+ wpa_ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapCACertInternal(const std::string &path)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (setStringFieldAndResetState(
+ path.c_str(), &(wpa_ssid->eap.cert.ca_cert), "eap ca_cert")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapCAPathInternal(const std::string &path)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (setStringFieldAndResetState(
+ path.c_str(), &(wpa_ssid->eap.cert.ca_path), "eap ca_path")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapClientCertInternal(const std::string &path)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (setStringFieldAndResetState(
+ path.c_str(), &(wpa_ssid->eap.cert.client_cert),
+ "eap client_cert")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapPrivateKeyIdInternal(const std::string &id)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (setStringFieldAndResetState(
+ id.c_str(), &(wpa_ssid->eap.cert.key_id), "eap key_id")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapSubjectMatchInternal(
+ const std::string &match)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (setStringFieldAndResetState(
+ match.c_str(), &(wpa_ssid->eap.cert.subject_match),
+ "eap subject_match")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapAltSubjectMatchInternal(
+ const std::string &match)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (setStringFieldAndResetState(
+ match.c_str(), &(wpa_ssid->eap.cert.altsubject_match),
+ "eap altsubject_match")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapEngineInternal(bool enable)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ wpa_ssid->eap.cert.engine = enable ? 1 : 0;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapEngineIDInternal(const std::string &id)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (setStringFieldAndResetState(
+ id.c_str(), &(wpa_ssid->eap.cert.engine_id), "eap engine_id")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setEapDomainSuffixMatchInternal(
+ const std::string &match)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (setStringFieldAndResetState(
+ match.c_str(), &(wpa_ssid->eap.cert.domain_suffix_match),
+ "eap domain_suffix_match")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setProactiveKeyCachingInternal(bool enable)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ wpa_ssid->proactive_key_caching = enable ? 1 : 0;
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setIdStrInternal(const std::string &id_str)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (setStringFieldAndResetState(
+ id_str.c_str(), &(wpa_ssid->id_str), "id_str")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setUpdateIdentifierInternal(uint32_t id)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ wpa_ssid->update_identifier = id;
+ wpa_printf(
+ MSG_MSGDUMP, "update_identifier: %d", wpa_ssid->update_identifier);
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setWapiCertSuiteInternal(const std::string &suite)
+{
+#ifdef CONFIG_WAPI_INTERFACE
+ // Dummy implementation
+ dummyWapiCertSuite = suite;
+ return ndk::ScopedAStatus::ok();
+#else
+ return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN, "Not implemented");
+#endif
+}
+
+ndk::ScopedAStatus StaNetwork::setWapiPskInternal(const std::vector<uint8_t> &psk)
+{
+#ifdef CONFIG_WAPI_INTERFACE
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ str_clear_free(wpa_ssid->passphrase);
+ wpa_ssid->passphrase = nullptr;
+
+ // Dummy implementation
+ dummyWapiPsk = psk;
+
+ wpa_ssid->psk_set = 1;
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+#else
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#endif
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> StaNetwork::getSsidInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ std::vector<uint8_t> ssid(
+ wpa_ssid->ssid,
+ wpa_ssid->ssid + wpa_ssid->ssid_len);
+ return {std::move(ssid), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaNetwork::getBssidInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ std::vector<uint8_t> bssid(kZeroBssid, kZeroBssid + ETH_ALEN);
+ if (wpa_ssid->bssid_set) {
+ bssid.assign(wpa_ssid->bssid, wpa_ssid->bssid + ETH_ALEN);
+ }
+ return {std::move(bssid), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> StaNetwork::getScanSsidInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ return {(wpa_ssid->scan_ssid == 1), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<AuthAlgMask, ndk::ScopedAStatus>
+StaNetwork::getAuthAlgInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ uint32_t auth_alg_mask = wpa_ssid->auth_alg & kAllowedAuthAlgMask;
+ return {static_cast<AuthAlgMask>(auth_alg_mask), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getPskPassphraseInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+#ifdef CONFIG_WAPI_INTERFACE
+ if (wpa_ssid->key_mgmt & WPA_KEY_MGMT_WAPI_PSK) {
+ if (wpa_ssid->psk_set) {
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> ret = getWapiPskInternal();
+ std::string psk;
+ char buf[3] = {0};
+ for (int i = 0; i < ret.second.size(); i++) {
+ snprintf(buf, sizeof(buf), "%02x", ret.second[i]);
+ psk.append(buf);
+ }
+ return {psk, ndk::ScopedAStatus::ok()};
+ } else {
+ if (!wpa_ssid->passphrase) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ std::string passphrase;
+ passphrase.append("\"");
+ passphrase.append(wpa_ssid->passphrase);
+ passphrase.append("\"");
+ return {passphrase, ndk::ScopedAStatus::ok()};
+ }
+ }
+#endif
+ if (!wpa_ssid->passphrase) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {wpa_ssid->passphrase, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaNetwork::getPskInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ WPA_ASSERT(psk.size() == sizeof(wpa_ssid->psk));
+ if (!wpa_ssid->psk_set) {
+ return {std::vector<uint8_t>(),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ std::vector<uint8_t> psk(wpa_ssid->psk, wpa_ssid->psk + 32);
+ return {psk, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getSaePasswordInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->sae_password) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::charBufToString(wpa_ssid->sae_password),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getSaePasswordIdInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->sae_password_id) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::charBufToString(wpa_ssid->sae_password_id),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> StaNetwork::getWepKeyInternal(
+ uint32_t key_idx)
+{
+ std::vector<uint8_t> wep_key;
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (key_idx >=
+ static_cast<uint32_t>(
+ ISupplicantStaNetwork::WEP_KEYS_MAX_NUM)) {
+ return {wep_key,
+ createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID)};
+ }
+ wep_key.assign(
+ wpa_ssid->wep_key[key_idx],
+ wpa_ssid->wep_key[key_idx] + wpa_ssid->wep_key_len[key_idx]);
+ return {std::move(wep_key), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<uint32_t, ndk::ScopedAStatus> StaNetwork::getWepTxKeyIdxInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ return {wpa_ssid->wep_tx_keyidx, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> StaNetwork::getRequirePmfInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ return {(wpa_ssid->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<EapMethod, ndk::ScopedAStatus>
+StaNetwork::getEapMethodInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.eap_methods) {
+ return {static_cast<EapMethod>(0),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ // wpa_supplicant can support setting multiple eap methods for each
+ // network. But, this is not really used by Android. So, just reading
+ // the first EAP method for each network.
+ const std::string eap_method_str = eap_get_name(
+ wpa_ssid->eap.eap_methods[0].vendor,
+ static_cast<enum eap_type>(wpa_ssid->eap.eap_methods[0].method));
+ size_t eap_method_idx =
+ std::find(
+ std::begin(kEapMethodStrings), std::end(kEapMethodStrings),
+ eap_method_str) -
+ std::begin(kEapMethodStrings);
+ if (eap_method_idx >= kEapMethodMax) {
+ return {static_cast<EapMethod>(0),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {static_cast<EapMethod>(eap_method_idx), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<EapPhase2Method, ndk::ScopedAStatus>
+StaNetwork::getEapPhase2MethodInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.phase2) {
+ return {static_cast<EapPhase2Method>(0),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ const std::string eap_phase2_method_str_with_prefix =
+ wpa_ssid->eap.phase2;
+ std::string eap_phase2_method_str;
+ // Strip out the phase 2 method prefix before doing a reverse lookup
+ // of phase 2 string to the Eap Phase 2 type.
+ if (eap_phase2_method_str_with_prefix.find(kEapPhase2AuthPrefix) == 0) {
+ eap_phase2_method_str =
+ eap_phase2_method_str_with_prefix.substr(
+ strlen(kEapPhase2AuthPrefix),
+ eap_phase2_method_str_with_prefix.size());
+ } else if (
+ eap_phase2_method_str_with_prefix.find(kEapPhase2AuthEapPrefix) ==
+ 0) {
+ eap_phase2_method_str =
+ eap_phase2_method_str_with_prefix.substr(
+ strlen(kEapPhase2AuthEapPrefix),
+ eap_phase2_method_str_with_prefix.size());
+ }
+ size_t eap_phase2_method_idx =
+ std::find(
+ std::begin(kEapPhase2MethodStrings),
+ std::end(kEapPhase2MethodStrings), eap_phase2_method_str) -
+ std::begin(kEapPhase2MethodStrings);
+ if (eap_phase2_method_idx >= kEapPhase2MethodMax) {
+ return {static_cast<EapPhase2Method>(0),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {static_cast<EapPhase2Method>(eap_phase2_method_idx),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaNetwork::getEapIdentityInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.identity) {
+ return {std::vector<uint8_t>(),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {std::vector<uint8_t>(
+ wpa_ssid->eap.identity,
+ wpa_ssid->eap.identity + wpa_ssid->eap.identity_len),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaNetwork::getEapAnonymousIdentityInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.anonymous_identity) {
+ return {std::vector<uint8_t>(),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {std::vector<uint8_t>(
+ wpa_ssid->eap.anonymous_identity,
+ wpa_ssid->eap.anonymous_identity +
+ wpa_ssid->eap.anonymous_identity_len),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaNetwork::getEapPasswordInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.password) {
+ return {std::vector<uint8_t>(), createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {std::vector<uint8_t>(
+ wpa_ssid->eap.password,
+ wpa_ssid->eap.password + wpa_ssid->eap.password_len),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getEapCACertInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.cert.ca_cert) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::charBufToString(wpa_ssid->eap.cert.ca_cert),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getEapCAPathInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.cert.ca_path) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::charBufToString(wpa_ssid->eap.cert.ca_path),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getEapClientCertInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.cert.client_cert) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::charBufToString(wpa_ssid->eap.cert.client_cert),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus>
+StaNetwork::getEapPrivateKeyIdInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.cert.key_id) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::charBufToString(reinterpret_cast<char *>(wpa_ssid->eap.cert.key_id)),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus>
+StaNetwork::getEapSubjectMatchInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.cert.subject_match) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::charBufToString(wpa_ssid->eap.cert.subject_match),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus>
+StaNetwork::getEapAltSubjectMatchInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.cert.altsubject_match) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::charBufToString(wpa_ssid->eap.cert.altsubject_match),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> StaNetwork::getEapEngineInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ return {wpa_ssid->eap.cert.engine == 1, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getEapEngineIdInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.cert.engine_id) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::charBufToString(wpa_ssid->eap.cert.engine_id),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus>
+StaNetwork::getEapDomainSuffixMatchInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->eap.cert.domain_suffix_match) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::charBufToString(wpa_ssid->eap.cert.domain_suffix_match),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getIdStrInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (!wpa_ssid->id_str) {
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::charBufToString(wpa_ssid->id_str),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<bool, ndk::ScopedAStatus> StaNetwork::getEdmgInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ return {(wpa_ssid->enable_edmg == 1), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+StaNetwork::getWpsNfcConfigurationTokenInternal()
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ auto token_buf = misc_utils::createWpaBufUniquePtr(
+ wpas_wps_network_config_token(wpa_s, 0, wpa_ssid));
+ if (!token_buf) {
+ return {std::vector<uint8_t>(),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {misc_utils::convertWpaBufToVector(token_buf.get()),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::string, ndk::ScopedAStatus> StaNetwork::getWapiCertSuiteInternal()
+{
+#ifdef CONFIG_WAPI_INTERFACE
+ // Dummy implementation
+ return {dummyWapiCertSuite, ndk::ScopedAStatus::ok()};
+#else
+ return {"", createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+#endif
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> StaNetwork::getWapiPskInternal()
+{
+#ifdef CONFIG_WAPI_INTERFACE
+ // Dummy implementation
+ return {dummyWapiPsk, ndk::ScopedAStatus::ok()};
+#else
+ return {std::vector<uint8_t>(),
+ createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+#endif
+}
+
+ndk::ScopedAStatus StaNetwork::enableInternal(bool no_connect)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (wpa_ssid->disabled == 2) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (no_connect) {
+ wpa_ssid->disabled = 0;
+ } else {
+ wpa_s->scan_min_time.sec = 0;
+ wpa_s->scan_min_time.usec = 0;
+ wpa_supplicant_enable_network(wpa_s, wpa_ssid);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::disableInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (wpa_ssid->disabled == 2) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ wpa_supplicant_disable_network(wpa_s, wpa_ssid);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::selectInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (wpa_ssid->disabled == 2) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ wpa_s->scan_min_time.sec = 0;
+ wpa_s->scan_min_time.usec = 0;
+ wpa_supplicant_select_network(wpa_s, wpa_ssid);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::sendNetworkEapSimGsmAuthResponseInternal(
+ const std::vector<NetworkResponseEapSimGsmAuthParams>
+ &vec_params)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ // Convert the incoming parameters to a string to pass to
+ // wpa_supplicant.
+ std::string ctrl_rsp_param = std::string(kNetworkEapSimGsmAuthResponse);
+ for (const auto ¶ms : vec_params) {
+ uint32_t kc_hex_len = params.kc.size() * 2 + 1;
+ std::vector<char> kc_hex(kc_hex_len);
+ uint32_t sres_hex_len = params.sres.size() * 2 + 1;
+ std::vector<char> sres_hex(sres_hex_len);
+ wpa_snprintf_hex(
+ kc_hex.data(), kc_hex.size(), params.kc.data(),
+ params.kc.size());
+ wpa_snprintf_hex(
+ sres_hex.data(), sres_hex.size(), params.sres.data(),
+ params.sres.size());
+ ctrl_rsp_param += ":" + std::string(kc_hex.data()) + ":" +
+ std::string(sres_hex.data());
+ }
+ enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (wpa_supplicant_ctrl_rsp_handle(
+ wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+ ctrl_rsp_param.size())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ eapol_sm_notify_ctrl_response(wpa_s->eapol);
+ wpa_hexdump_ascii_key(
+ MSG_DEBUG, "network sim gsm auth response param",
+ (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::sendNetworkEapSimGsmAuthFailureInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+ if (wpa_supplicant_ctrl_rsp_handle(
+ wpa_s, wpa_ssid, rtype, kNetworkEapSimGsmAuthFailure,
+ strlen(kNetworkEapSimGsmAuthFailure))) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ eapol_sm_notify_ctrl_response(wpa_s->eapol);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::sendNetworkEapSimUmtsAuthResponseInternal(
+ const NetworkResponseEapSimUmtsAuthParams ¶ms)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ // Convert the incoming parameters to a string to pass to
+ // wpa_supplicant.
+ uint32_t ik_hex_len = params.ik.size() * 2 + 1;
+ std::vector<char> ik_hex(ik_hex_len);
+ uint32_t ck_hex_len = params.ck.size() * 2 + 1;
+ std::vector<char> ck_hex(ck_hex_len);
+ uint32_t res_hex_len = params.res.size() * 2 + 1;
+ std::vector<char> res_hex(res_hex_len);
+ wpa_snprintf_hex(
+ ik_hex.data(), ik_hex.size(), params.ik.data(), params.ik.size());
+ wpa_snprintf_hex(
+ ck_hex.data(), ck_hex.size(), params.ck.data(), params.ck.size());
+ wpa_snprintf_hex(
+ res_hex.data(), res_hex.size(), params.res.data(),
+ params.res.size());
+ std::string ctrl_rsp_param =
+ std::string(kNetworkEapSimUmtsAuthResponse) + ":" +
+ std::string(ik_hex.data()) + ":" + std::string(ck_hex.data()) +
+ ":" + std::string(res_hex.data());
+ enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (wpa_supplicant_ctrl_rsp_handle(
+ wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+ ctrl_rsp_param.size())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ eapol_sm_notify_ctrl_response(wpa_s->eapol);
+ wpa_hexdump_ascii_key(
+ MSG_DEBUG, "network sim umts auth response param",
+ (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::sendNetworkEapSimUmtsAutsResponseInternal(
+ const std::vector<uint8_t> &auts)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ uint32_t auts_hex_len = auts.size() * 2 + 1;
+ std::vector<char> auts_hex(auts_hex_len);
+ wpa_snprintf_hex(
+ auts_hex.data(), auts_hex.size(), auts.data(), auts.size());
+ std::string ctrl_rsp_param =
+ std::string(kNetworkEapSimUmtsAutsResponse) + ":" +
+ std::string(auts_hex.data());
+ enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (wpa_supplicant_ctrl_rsp_handle(
+ wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+ ctrl_rsp_param.size())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ eapol_sm_notify_ctrl_response(wpa_s->eapol);
+ wpa_hexdump_ascii_key(
+ MSG_DEBUG, "network sim umts auts response param",
+ (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::sendNetworkEapSimUmtsAuthFailureInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+ if (wpa_supplicant_ctrl_rsp_handle(
+ wpa_s, wpa_ssid, rtype, kNetworkEapSimUmtsAuthFailure,
+ strlen(kNetworkEapSimUmtsAuthFailure))) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ eapol_sm_notify_ctrl_response(wpa_s->eapol);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::sendNetworkEapIdentityResponseInternal(
+ const std::vector<uint8_t> &identity,
+ const std::vector<uint8_t> &encrypted_imsi_identity)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ std::string ctrl_rsp_param(identity.begin(), identity.end());
+ // If encrypted identity is included, format is:
+ // plain identity + ":" + encrypted_identity
+ if (encrypted_imsi_identity.size() != 0) {
+ ctrl_rsp_param += ":" + std::string(
+ encrypted_imsi_identity.begin(), encrypted_imsi_identity.end());
+ }
+ enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_EAP_IDENTITY;
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (wpa_supplicant_ctrl_rsp_handle(
+ wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+ ctrl_rsp_param.size())) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ eapol_sm_notify_ctrl_response(wpa_s->eapol);
+ wpa_hexdump_ascii_key(
+ MSG_DEBUG, "network identity response param",
+ (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::enableTlsSuiteBEapPhase1ParamInternal(bool enable)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ int val = enable == true ? 1 : 0;
+ std::string suiteb_phase1("tls_suiteb=" + std::to_string(val));
+
+ if (setStringKeyFieldAndResetState(
+ suiteb_phase1.c_str(), &(wpa_ssid->eap.phase1), "phase1")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::enableSuiteBEapOpenSslCiphersInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ const char openssl_suiteb_cipher[] = "SUITEB192";
+
+ if (setStringKeyFieldAndResetState(
+ openssl_suiteb_cipher, &(wpa_ssid->eap.openssl_ciphers),
+ "openssl_ciphers")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setSaePasswordInternal(
+ const std::string &sae_password)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (sae_password.length() < 1) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ if (wpa_ssid->sae_password &&
+ os_strlen(wpa_ssid->sae_password) == sae_password.length() &&
+ os_memcmp(
+ wpa_ssid->sae_password, sae_password.c_str(),
+ sae_password.length()) == 0) {
+ return ndk::ScopedAStatus::ok();
+ }
+ wpa_ssid->psk_set = 1;
+ if (setStringKeyFieldAndResetState(
+ sae_password.c_str(), &(wpa_ssid->sae_password),
+ "sae password")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setSaePasswordIdInternal(
+ const std::string &sae_password_id)
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (sae_password_id.length() < 1) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ if (wpa_ssid->sae_password_id &&
+ os_strlen(wpa_ssid->sae_password_id) == sae_password_id.length() &&
+ os_memcmp(
+ wpa_ssid->sae_password_id, sae_password_id.c_str(),
+ sae_password_id.length()) == 0) {
+ return ndk::ScopedAStatus::ok();
+ }
+ wpa_ssid->psk_set = 1;
+ if (setStringKeyFieldAndResetState(
+ sae_password_id.c_str(), &(wpa_ssid->sae_password_id),
+ "sae password id")) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setGroupMgmtCipherInternal(
+ GroupMgmtCipherMask mask)
+{
+ uint32_t group_mgmt_cipher_mask = static_cast<uint32_t>(mask);
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (group_mgmt_cipher_mask & ~kAllowedGroupMgmtCipherMask) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ wpa_ssid->group_mgmt_cipher = group_mgmt_cipher_mask;
+ wpa_printf(MSG_MSGDUMP, "group_mgmt_cipher: 0x%x",
+ wpa_ssid->group_mgmt_cipher);
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<GroupMgmtCipherMask, ndk::ScopedAStatus>
+StaNetwork::getGroupMgmtCipherInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ uint32_t group_mgmt_cipher_mask =
+ wpa_ssid->group_mgmt_cipher & kAllowedGroupMgmtCipherMask;
+ return {static_cast<GroupMgmtCipherMask>(group_mgmt_cipher_mask),
+ ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::setOcspInternal(OcspType ocspType) {
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (ocspType < OcspType::NONE || ocspType > OcspType::REQUIRE_ALL_CERTS_STATUS) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ wpa_ssid->eap.cert.ocsp = (int) ocspType;
+ wpa_printf(
+ MSG_MSGDUMP, "ocsp: %d", wpa_ssid->eap.cert.ocsp);
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<OcspType, ndk::ScopedAStatus> StaNetwork::getOcspInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ return {static_cast<OcspType>(wpa_ssid->eap.cert.ocsp),
+ ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::setPmkCacheInternal(const std::vector<uint8_t>& serializedEntry) {
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ struct rsn_pmksa_cache_entry *new_entry = NULL;
+
+ new_entry = (struct rsn_pmksa_cache_entry *) os_zalloc(sizeof(*new_entry));
+ if (!new_entry) {
+ return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+ "Allocating memory failed");
+ }
+
+ std::stringstream ss(
+ std::stringstream::in | std::stringstream::out | std::stringstream::binary);
+ ss.write((char *) serializedEntry.data(), std::streamsize(serializedEntry.size()));
+ misc_utils::deserializePmkCacheEntry(ss, new_entry);
+ new_entry->network_ctx = wpa_ssid;
+ wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, new_entry);
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::setKeyMgmtInternal(
+ KeyMgmtMask mask)
+{
+ uint32_t key_mgmt_mask = static_cast<uint32_t>(mask);
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (key_mgmt_mask & ~kAllowedKeyMgmtMask) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ setFastTransitionKeyMgmt(key_mgmt_mask);
+
+ if (key_mgmt_mask & WPA_KEY_MGMT_OWE) {
+ // Do not allow to connect to Open network when OWE is selected
+ wpa_ssid->owe_only = 1;
+ }
+ wpa_ssid->key_mgmt = key_mgmt_mask;
+ wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", wpa_ssid->key_mgmt);
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<KeyMgmtMask, ndk::ScopedAStatus>
+StaNetwork::getKeyMgmtInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ uint32_t key_mgmt_mask = wpa_ssid->key_mgmt & kAllowedKeyMgmtMask;
+
+ resetFastTransitionKeyMgmt(key_mgmt_mask);
+ return {static_cast<KeyMgmtMask>(key_mgmt_mask),
+ ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::setProtoInternal(
+ ProtoMask mask)
+{
+ uint32_t proto_mask = static_cast<uint32_t>(mask);
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (proto_mask & ~kAllowedProtoMask) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ wpa_ssid->proto = proto_mask;
+ wpa_printf(MSG_MSGDUMP, "proto: 0x%x", wpa_ssid->proto);
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<ProtoMask, ndk::ScopedAStatus>
+StaNetwork::getProtoInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ uint32_t proto_mask = wpa_ssid->proto & kAllowedProtoMask;
+ return {static_cast<ProtoMask>(proto_mask), ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::setGroupCipherInternal(
+ GroupCipherMask mask)
+{
+ uint32_t group_cipher_mask = static_cast<uint32_t>(mask);
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (group_cipher_mask & ~kAllowedGroupCipherMask) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ wpa_ssid->group_cipher = group_cipher_mask;
+ wpa_printf(MSG_MSGDUMP, "group_cipher: 0x%x", wpa_ssid->group_cipher);
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<GroupCipherMask, ndk::ScopedAStatus>
+StaNetwork::getGroupCipherInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ uint32_t group_cipher_mask = wpa_ssid->group_cipher & kAllowedGroupCipherMask;
+ return {static_cast<GroupCipherMask>(group_cipher_mask),
+ ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus StaNetwork::setPairwiseCipherInternal(
+ PairwiseCipherMask mask)
+{
+ uint32_t pairwise_cipher_mask = static_cast<uint32_t>(mask);
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ if (pairwise_cipher_mask & ~kAllowedPairwisewCipherMask) {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ wpa_ssid->pairwise_cipher = pairwise_cipher_mask;
+ wpa_printf(
+ MSG_MSGDUMP, "pairwise_cipher: 0x%x", wpa_ssid->pairwise_cipher);
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<PairwiseCipherMask, ndk::ScopedAStatus>
+StaNetwork::getPairwiseCipherInternal()
+{
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ uint32_t pairwise_cipher_mask = wpa_ssid->pairwise_cipher & kAllowedPairwisewCipherMask;
+ return {static_cast<PairwiseCipherMask>(pairwise_cipher_mask),
+ ndk::ScopedAStatus::ok()};
+}
+
+/**
+ * Retrieve the underlying |wpa_ssid| struct pointer for
+ * this network.
+ * If the underlying network is removed or the interface
+ * this network belong to
+ * is removed, all RPC method calls on this object will
+ * return failure.
+ */
+struct wpa_ssid *StaNetwork::retrieveNetworkPtr()
+{
+ wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (!wpa_s)
+ return nullptr;
+ return wpa_config_get_network(wpa_s->conf, network_id_);
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for
+ * this network.
+ */
+struct wpa_supplicant *StaNetwork::retrieveIfacePtr()
+{
+ return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
+}
+
+/**
+ * Check if the provided psk passhrase is valid or not.
+ *
+ * Returns 0 if valid, 1 otherwise.
+ */
+int StaNetwork::isPskPassphraseValid(const std::string &psk)
+{
+ if (psk.size() <
+ static_cast<uint32_t>(ISupplicantStaNetwork::
+ PSK_PASSPHRASE_MIN_LEN_IN_BYTES) ||
+ psk.size() >
+ static_cast<uint32_t>(ISupplicantStaNetwork::
+ PSK_PASSPHRASE_MAX_LEN_IN_BYTES)) {
+ return 1;
+ }
+ if (has_ctrl_char((u8 *)psk.c_str(), psk.size())) {
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Reset internal wpa_supplicant state machine state
+ * after params update (except
+ * bssid).
+ */
+void StaNetwork::resetInternalStateAfterParamsUpdate()
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_ssid);
+
+ if (wpa_s->current_ssid == wpa_ssid || wpa_s->current_ssid == NULL) {
+ /*
+ * Invalidate the EAP session cache if
+ * anything in the
+ * current or previously used
+ * configuration changes.
+ */
+ eapol_sm_invalidate_cached_session(wpa_s->eapol);
+ }
+}
+
+/**
+ * Helper function to set value in a string field in |wpa_ssid| structue
+ * instance for this network.
+ * This function frees any existing data in these fields.
+ */
+int StaNetwork::setStringFieldAndResetState(
+ const char *value, uint8_t **to_update_field, const char *hexdump_prefix)
+{
+ return setStringFieldAndResetState(
+ value, (char **)to_update_field, hexdump_prefix);
+}
+
+/**
+ * Helper function to set value in a string field in |wpa_ssid| structue
+ * instance for this network.
+ * This function frees any existing data in these fields.
+ */
+int StaNetwork::setStringFieldAndResetState(
+ const char *value, char **to_update_field, const char *hexdump_prefix)
+{
+ int value_len = strlen(value);
+ if (*to_update_field) {
+ os_free(*to_update_field);
+ }
+ *to_update_field = dup_binstr(value, value_len);
+ if (!(*to_update_field)) {
+ return 1;
+ }
+ wpa_hexdump_ascii(
+ MSG_MSGDUMP, hexdump_prefix, *to_update_field, value_len);
+ resetInternalStateAfterParamsUpdate();
+ return 0;
+}
+
+/**
+ * Helper function to set value in a string key field in |wpa_ssid| structue
+ * instance for this network.
+ * This function frees any existing data in these fields.
+ */
+int StaNetwork::setStringKeyFieldAndResetState(
+ const char *value, char **to_update_field, const char *hexdump_prefix)
+{
+ int value_len = strlen(value);
+ if (*to_update_field) {
+ str_clear_free(*to_update_field);
+ }
+ *to_update_field = dup_binstr(value, value_len);
+ if (!(*to_update_field)) {
+ return 1;
+ }
+ wpa_hexdump_ascii_key(
+ MSG_MSGDUMP, hexdump_prefix, *to_update_field, value_len);
+ resetInternalStateAfterParamsUpdate();
+ return 0;
+}
+
+/**
+ * Helper function to set value in a string field with a corresponding length
+ * field in |wpa_ssid| structure instance for this network.
+ * This function frees any existing data in these fields.
+ */
+int StaNetwork::setByteArrayFieldAndResetState(
+ const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
+ size_t *to_update_field_len, const char *hexdump_prefix)
+{
+ if (*to_update_field) {
+ os_free(*to_update_field);
+ }
+ *to_update_field = (uint8_t *)os_malloc(value_len);
+ if (!(*to_update_field)) {
+ return 1;
+ }
+ os_memcpy(*to_update_field, value, value_len);
+ *to_update_field_len = value_len;
+
+ wpa_hexdump_ascii(
+ MSG_MSGDUMP, hexdump_prefix, *to_update_field,
+ *to_update_field_len);
+ resetInternalStateAfterParamsUpdate();
+ return 0;
+}
+
+/**
+ * Helper function to set value in a string key field with a corresponding
+ * length field in |wpa_ssid| structue instance for this network.
+ * This function frees any existing data in these fields.
+ */
+int StaNetwork::setByteArrayKeyFieldAndResetState(
+ const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
+ size_t *to_update_field_len, const char *hexdump_prefix)
+{
+ if (*to_update_field) {
+ bin_clear_free(*to_update_field, *to_update_field_len);
+ }
+ *to_update_field = (uint8_t *)os_malloc(value_len);
+ if (!(*to_update_field)) {
+ return 1;
+ }
+ os_memcpy(*to_update_field, value, value_len);
+ *to_update_field_len = value_len;
+
+ wpa_hexdump_ascii_key(
+ MSG_MSGDUMP, hexdump_prefix, *to_update_field,
+ *to_update_field_len);
+ resetInternalStateAfterParamsUpdate();
+ return 0;
+}
+
+/**
+ * Helper function to set the fast transition bits in the key management
+ * bitmask, to allow FT support when possible.
+ */
+void StaNetwork::setFastTransitionKeyMgmt(uint32_t &key_mgmt_mask)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ int res;
+ struct wpa_driver_capa capa;
+
+ if (key_mgmt_mask & WPA_KEY_MGMT_PSK) {
+ key_mgmt_mask |= WPA_KEY_MGMT_FT_PSK;
+ }
+
+ if (key_mgmt_mask & WPA_KEY_MGMT_IEEE8021X) {
+ key_mgmt_mask |= WPA_KEY_MGMT_FT_IEEE8021X;
+ }
+
+ res = wpa_drv_get_capa(wpa_s, &capa);
+ if (res == 0) {
+#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_SAE
+ if ((key_mgmt_mask & WPA_KEY_MGMT_SAE) &&
+ (capa.key_mgmt_iftype[WPA_IF_STATION] & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE)) {
+ key_mgmt_mask |= WPA_KEY_MGMT_FT_SAE;
+ }
+#endif
+#endif
+ }
+
+}
+
+/**
+ * Helper function to reset the fast transition bits in the key management
+ * bitmask.
+ */
+void StaNetwork::resetFastTransitionKeyMgmt(uint32_t &key_mgmt_mask)
+{
+ if (key_mgmt_mask & WPA_KEY_MGMT_PSK) {
+ key_mgmt_mask &= ~WPA_KEY_MGMT_FT_PSK;
+ }
+
+ if (key_mgmt_mask & WPA_KEY_MGMT_IEEE8021X) {
+ key_mgmt_mask &= ~WPA_KEY_MGMT_FT_IEEE8021X;
+ }
+#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_SAE
+ if (key_mgmt_mask & WPA_KEY_MGMT_SAE) {
+ key_mgmt_mask &= ~WPA_KEY_MGMT_FT_SAE;
+ }
+#endif
+#endif
+}
+
+/**
+ * Helper function to enable erp keys generation while connecting to FILS
+ * enabled APs.
+ */
+ndk::ScopedAStatus StaNetwork::setEapErpInternal(bool enable)
+{
+#ifdef CONFIG_FILS
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ wpa_ssid->eap.erp = enable ? 1 : 0;
+ return ndk::ScopedAStatus::ok();
+#else /* CONFIG_FILS */
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+#endif /* CONFIG_FILS */
+}
+
+ndk::ScopedAStatus StaNetwork::setSaeH2eModeInternal(
+ SaeH2eMode mode)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ switch (mode) {
+ case SaeH2eMode::DISABLED:
+ wpa_s->conf->sae_pwe = 0;
+ break;
+ case SaeH2eMode::H2E_MANDATORY:
+ wpa_s->conf->sae_pwe = 1;
+ break;
+ case SaeH2eMode::H2E_OPTIONAL:
+ wpa_s->conf->sae_pwe = 2;
+ break;
+ }
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaNetwork::enableSaePkOnlyModeInternal(bool enable)
+{
+#ifdef CONFIG_SAE_PK
+ struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+ wpa_ssid->sae_pk = enable ? SAE_PK_MODE_ONLY : SAE_PK_MODE_AUTOMATIC;
+ resetInternalStateAfterParamsUpdate();
+ return ndk::ScopedAStatus::ok();
+#else
+ return createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED);
+#endif
+}
+
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wpa_supplicant/aidl/sta_network.h b/wpa_supplicant/aidl/sta_network.h
new file mode 100644
index 0000000..f1ef1ad
--- /dev/null
+++ b/wpa_supplicant/aidl/sta_network.h
@@ -0,0 +1,342 @@
+/*
+ * WPA Supplicant - Sta network Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_STA_NETWORK_H
+#define WPA_SUPPLICANT_AIDL_STA_NETWORK_H
+
+#include <array>
+#include <vector>
+
+#include <android-base/macros.h>
+
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantStaNetwork.h>
+#include <aidl/android/hardware/wifi/supplicant/EapMethod.h>
+#include <aidl/android/hardware/wifi/supplicant/EapPhase2Method.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.h>
+#include <aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.h>
+#include <aidl/android/hardware/wifi/supplicant/SaeH2eMode.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "config.h"
+#include "wpa_supplicant_i.h"
+#include "notify.h"
+#include "eapol_supp/eapol_supp_sm.h"
+#include "eap_peer/eap.h"
+#include "rsn_supp/wpa.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+/**
+ * Implementation of StaNetwork aidl object. Each unique aidl
+ * object is used for control operations on a specific network
+ * controlled by wpa_supplicant.
+ */
+class StaNetwork : public BnSupplicantStaNetwork
+{
+public:
+ StaNetwork(
+ struct wpa_global* wpa_global, const char ifname[], int network_id);
+ ~StaNetwork() override = default;
+ // Refer to |StaIface::invalidate()|.
+ void invalidate();
+ bool isValid();
+
+ // Aidl methods exposed.
+ ::ndk::ScopedAStatus getId(int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus getInterfaceName(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getType(IfaceType* _aidl_return) override;
+ ::ndk::ScopedAStatus registerCallback(
+ const std::shared_ptr<ISupplicantStaNetworkCallback>& in_callback) override;
+ ::ndk::ScopedAStatus setSsid(const std::vector<uint8_t>& in_ssid) override;
+ ::ndk::ScopedAStatus setBssid(const std::vector<uint8_t>& in_bssid) override;
+ ::ndk::ScopedAStatus setScanSsid(bool in_enable) override;
+ ::ndk::ScopedAStatus setKeyMgmt(KeyMgmtMask in_keyMgmtMask) override;
+ ::ndk::ScopedAStatus setProto(ProtoMask in_protoMask) override;
+ ::ndk::ScopedAStatus setAuthAlg(AuthAlgMask in_authAlgMask) override;
+ ::ndk::ScopedAStatus setGroupCipher(GroupCipherMask in_groupCipherMask) override;
+ ::ndk::ScopedAStatus setPairwiseCipher(
+ PairwiseCipherMask in_pairwiseCipherMask) override;
+ ::ndk::ScopedAStatus setPskPassphrase(const std::string& in_psk) override;
+ ::ndk::ScopedAStatus setPsk(const std::vector<uint8_t>& in_psk) override;
+ ::ndk::ScopedAStatus setWepKey(
+ int32_t in_keyIdx, const std::vector<uint8_t>& in_wepKey) override;
+ ::ndk::ScopedAStatus setWepTxKeyIdx(int32_t in_keyIdx) override;
+ ::ndk::ScopedAStatus setRequirePmf(bool in_enable) override;
+ ::ndk::ScopedAStatus setEapMethod(EapMethod in_method) override;
+ ::ndk::ScopedAStatus setEapPhase2Method(EapPhase2Method in_method) override;
+ ::ndk::ScopedAStatus setEapIdentity(
+ const std::vector<uint8_t>& in_identity) override;
+ ::ndk::ScopedAStatus setEapEncryptedImsiIdentity(
+ const std::vector<uint8_t>& in_identity) override;
+ ::ndk::ScopedAStatus setEapAnonymousIdentity(
+ const std::vector<uint8_t>& in_identity) override;
+ ::ndk::ScopedAStatus setEapPassword(
+ const std::vector<uint8_t>& in_password) override;
+ ::ndk::ScopedAStatus setEapCACert(const std::string& in_path) override;
+ ::ndk::ScopedAStatus setEapCAPath(const std::string& in_path) override;
+ ::ndk::ScopedAStatus setEapClientCert(const std::string& in_path) override;
+ ::ndk::ScopedAStatus setEapPrivateKeyId(const std::string& in_id) override;
+ ::ndk::ScopedAStatus setEapSubjectMatch(const std::string& in_match) override;
+ ::ndk::ScopedAStatus setEapAltSubjectMatch(const std::string& in_match) override;
+ ::ndk::ScopedAStatus setEapEngine(bool in_enable) override;
+ ::ndk::ScopedAStatus setEapEngineID(const std::string& in_id) override;
+ ::ndk::ScopedAStatus setEapDomainSuffixMatch(
+ const std::string& in_match) override;
+ ::ndk::ScopedAStatus setProactiveKeyCaching(bool in_enable) override;
+ ::ndk::ScopedAStatus setIdStr(const std::string& in_idStr) override;
+ ::ndk::ScopedAStatus setUpdateIdentifier(int32_t in_id) override;
+ ::ndk::ScopedAStatus setEdmg(bool in_enable) override;
+ ::ndk::ScopedAStatus getSsid(std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus getBssid(std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus getScanSsid(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus getKeyMgmt(KeyMgmtMask* _aidl_return) override;
+ ::ndk::ScopedAStatus getProto(ProtoMask* _aidl_return) override;
+ ::ndk::ScopedAStatus getAuthAlg(AuthAlgMask* _aidl_return) override;
+ ::ndk::ScopedAStatus getGroupCipher(GroupCipherMask* _aidl_return) override;
+ ::ndk::ScopedAStatus getPairwiseCipher(PairwiseCipherMask* _aidl_return) override;
+ ::ndk::ScopedAStatus getPskPassphrase(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getPsk(std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus getSaePassword(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getSaePasswordId(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getWepKey(
+ int32_t in_keyIdx, std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus getWepTxKeyIdx(int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus getRequirePmf(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapMethod(EapMethod* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapPhase2Method(EapPhase2Method* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapIdentity(std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapAnonymousIdentity(
+ std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapPassword(std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapCACert(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapCAPath(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapClientCert(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapPrivateKeyId(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapSubjectMatch(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapAltSubjectMatch(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapEngine(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapEngineId(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getEapDomainSuffixMatch(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getIdStr(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus getWpsNfcConfigurationToken(
+ std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus getEdmg(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus enable(bool in_noConnect) override;
+ ::ndk::ScopedAStatus disable() override;
+ ::ndk::ScopedAStatus select() override;
+ ::ndk::ScopedAStatus sendNetworkEapSimGsmAuthResponse(
+ const std::vector<NetworkResponseEapSimGsmAuthParams>& in_params) override;
+ ::ndk::ScopedAStatus sendNetworkEapSimGsmAuthFailure() override;
+ ::ndk::ScopedAStatus sendNetworkEapSimUmtsAuthResponse(
+ const NetworkResponseEapSimUmtsAuthParams& in_params) override;
+ ::ndk::ScopedAStatus sendNetworkEapSimUmtsAutsResponse(
+ const std::vector<uint8_t>& in_auts) override;
+ ::ndk::ScopedAStatus sendNetworkEapSimUmtsAuthFailure() override;
+ ::ndk::ScopedAStatus sendNetworkEapIdentityResponse(
+ const std::vector<uint8_t>& in_identity,
+ const std::vector<uint8_t>& in_encryptedIdentity) override;
+ ::ndk::ScopedAStatus setGroupMgmtCipher(
+ GroupMgmtCipherMask in_groupMgmtCipherMask) override;
+ ::ndk::ScopedAStatus getGroupMgmtCipher(
+ GroupMgmtCipherMask* _aidl_return) override;
+ ::ndk::ScopedAStatus enableTlsSuiteBEapPhase1Param(
+ bool in_enable) override;
+ ::ndk::ScopedAStatus enableSuiteBEapOpenSslCiphers() override;
+ ::ndk::ScopedAStatus setSaePassword(
+ const std::string& in_saePassword) override;
+ ::ndk::ScopedAStatus setSaePasswordId(
+ const std::string& in_saePasswordId) override;
+ ::ndk::ScopedAStatus setOcsp(OcspType in_ocspType) override;
+ ::ndk::ScopedAStatus getOcsp(OcspType* _aidl_return) override;
+ ::ndk::ScopedAStatus setPmkCache(
+ const std::vector<uint8_t>& in_serializedEntry) override;
+ ::ndk::ScopedAStatus setWapiCertSuite(const std::string& in_suite) override;
+ ::ndk::ScopedAStatus getWapiCertSuite(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus setEapErp(bool in_enable) override;
+ ::ndk::ScopedAStatus setSaeH2eMode(SaeH2eMode in_mode) override;
+ ::ndk::ScopedAStatus enableSaePkOnlyMode(bool in_enable) override;
+
+private:
+ // Corresponding worker functions for the AIDL methods.
+ std::pair<uint32_t, ndk::ScopedAStatus> getIdInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getInterfaceNameInternal();
+ std::pair<IfaceType, ndk::ScopedAStatus> getTypeInternal();
+ ndk::ScopedAStatus registerCallbackInternal(
+ const std::shared_ptr<ISupplicantStaNetworkCallback>& callback);
+ ndk::ScopedAStatus setSsidInternal(const std::vector<uint8_t>& ssid);
+ ndk::ScopedAStatus setBssidInternal(const std::vector<uint8_t>& bssid);
+ ndk::ScopedAStatus setScanSsidInternal(bool enable);
+ ndk::ScopedAStatus setKeyMgmtInternal(
+ KeyMgmtMask mask);
+ ndk::ScopedAStatus setProtoInternal(
+ ProtoMask mask);
+ ndk::ScopedAStatus setAuthAlgInternal(
+ AuthAlgMask mask);
+ ndk::ScopedAStatus setGroupCipherInternal(
+ GroupCipherMask mask);
+ ndk::ScopedAStatus setPairwiseCipherInternal(
+ PairwiseCipherMask mask);
+ ndk::ScopedAStatus setPskPassphraseInternal(const std::string& psk);
+ ndk::ScopedAStatus setPskInternal(const std::vector<uint8_t>& psk);
+ ndk::ScopedAStatus setWepKeyInternal(
+ uint32_t key_idx, const std::vector<uint8_t>& wep_key);
+ ndk::ScopedAStatus setWepTxKeyIdxInternal(uint32_t key_idx);
+ ndk::ScopedAStatus setRequirePmfInternal(bool enable);
+ ndk::ScopedAStatus setEapMethodInternal(
+ EapMethod method);
+ ndk::ScopedAStatus setEapPhase2MethodInternal(
+ EapPhase2Method method);
+ ndk::ScopedAStatus setEapIdentityInternal(
+ const std::vector<uint8_t>& identity);
+ ndk::ScopedAStatus setEapEncryptedImsiIdentityInternal(
+ const std::vector<uint8_t>& identity);
+ ndk::ScopedAStatus setEapAnonymousIdentityInternal(
+ const std::vector<uint8_t>& identity);
+ ndk::ScopedAStatus setEapPasswordInternal(
+ const std::vector<uint8_t>& password);
+ ndk::ScopedAStatus setEapCACertInternal(const std::string& path);
+ ndk::ScopedAStatus setEapCAPathInternal(const std::string& path);
+ ndk::ScopedAStatus setEapClientCertInternal(const std::string& path);
+ ndk::ScopedAStatus setEapPrivateKeyIdInternal(const std::string& id);
+ ndk::ScopedAStatus setEapSubjectMatchInternal(const std::string& match);
+ ndk::ScopedAStatus setEapAltSubjectMatchInternal(
+ const std::string& match);
+ ndk::ScopedAStatus setEapEngineInternal(bool enable);
+ ndk::ScopedAStatus setEapEngineIDInternal(const std::string& id);
+ ndk::ScopedAStatus setEapDomainSuffixMatchInternal(
+ const std::string& match);
+ ndk::ScopedAStatus setProactiveKeyCachingInternal(bool enable);
+ ndk::ScopedAStatus setIdStrInternal(const std::string& id_str);
+ ndk::ScopedAStatus setUpdateIdentifierInternal(uint32_t id);
+ ndk::ScopedAStatus setEdmgInternal(bool enable);
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getSsidInternal();
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getBssidInternal();
+ std::pair<bool, ndk::ScopedAStatus> getScanSsidInternal();
+ std::pair<KeyMgmtMask, ndk::ScopedAStatus> getKeyMgmtInternal();
+ std::pair<ProtoMask, ndk::ScopedAStatus> getProtoInternal();
+ std::pair<AuthAlgMask, ndk::ScopedAStatus> getAuthAlgInternal();
+ std::pair<GroupCipherMask, ndk::ScopedAStatus> getGroupCipherInternal();
+ std::pair<PairwiseCipherMask, ndk::ScopedAStatus> getPairwiseCipherInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getPskPassphraseInternal();
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getPskInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getSaePasswordInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getSaePasswordIdInternal();
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getWepKeyInternal(
+ uint32_t key_idx);
+ std::pair<uint32_t, ndk::ScopedAStatus> getWepTxKeyIdxInternal();
+ std::pair<bool, ndk::ScopedAStatus> getRequirePmfInternal();
+ std::pair<EapMethod, ndk::ScopedAStatus> getEapMethodInternal();
+ std::pair<EapPhase2Method, ndk::ScopedAStatus>
+ getEapPhase2MethodInternal();
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+ getEapIdentityInternal();
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+ getEapAnonymousIdentityInternal();
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+ getEapPasswordInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getEapCACertInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getEapCAPathInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getEapClientCertInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getEapPrivateKeyIdInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getEapSubjectMatchInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getEapAltSubjectMatchInternal();
+ std::pair<bool, ndk::ScopedAStatus> getEapEngineInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getEapEngineIdInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getEapDomainSuffixMatchInternal();
+ std::pair<std::string, ndk::ScopedAStatus> getIdStrInternal();
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+ getWpsNfcConfigurationTokenInternal();
+ std::pair<bool, ndk::ScopedAStatus> getEdmgInternal();
+ ndk::ScopedAStatus enableInternal(bool no_connect);
+ ndk::ScopedAStatus disableInternal();
+ ndk::ScopedAStatus selectInternal();
+ ndk::ScopedAStatus sendNetworkEapSimGsmAuthResponseInternal(
+ const std::vector<NetworkResponseEapSimGsmAuthParams>&
+ vec_params);
+ ndk::ScopedAStatus sendNetworkEapSimGsmAuthFailureInternal();
+ ndk::ScopedAStatus sendNetworkEapSimUmtsAuthResponseInternal(
+ const NetworkResponseEapSimUmtsAuthParams& params);
+ ndk::ScopedAStatus sendNetworkEapSimUmtsAutsResponseInternal(
+ const std::vector<uint8_t>& auts);
+ ndk::ScopedAStatus sendNetworkEapSimUmtsAuthFailureInternal();
+ ndk::ScopedAStatus sendNetworkEapIdentityResponseInternal(
+ const std::vector<uint8_t>& identity,
+ const std::vector<uint8_t>& imsi_identity);
+ ndk::ScopedAStatus enableTlsSuiteBEapPhase1ParamInternal(bool enable);
+ ndk::ScopedAStatus enableSuiteBEapOpenSslCiphersInternal();
+ ndk::ScopedAStatus setSaePasswordInternal(
+ const std::string& sae_password);
+ ndk::ScopedAStatus setSaePasswordIdInternal(
+ const std::string& sae_password_id);
+ ndk::ScopedAStatus setGroupMgmtCipherInternal(
+ GroupMgmtCipherMask mask);
+ std::pair<GroupMgmtCipherMask, ndk::ScopedAStatus>
+ getGroupMgmtCipherInternal();
+ ndk::ScopedAStatus setOcspInternal(OcspType ocspType);
+ std::pair<OcspType, ndk::ScopedAStatus> getOcspInternal();
+ ndk::ScopedAStatus setPmkCacheInternal(const std::vector<uint8_t>& serializedEntry);
+ ndk::ScopedAStatus setWapiCertSuiteInternal(const std::string& suite);
+ std::pair<std::string, ndk::ScopedAStatus> getWapiCertSuiteInternal();
+ ndk::ScopedAStatus setWapiPskInternal(const std::vector<uint8_t>& psk);
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> getWapiPskInternal();
+ ndk::ScopedAStatus setSaeH2eModeInternal(SaeH2eMode mode);
+ ndk::ScopedAStatus enableSaePkOnlyModeInternal(bool enable);
+
+ struct wpa_ssid* retrieveNetworkPtr();
+ struct wpa_supplicant* retrieveIfacePtr();
+ int isPskPassphraseValid(const std::string& psk);
+ void resetInternalStateAfterParamsUpdate();
+ int setStringFieldAndResetState(
+ const char* value, uint8_t** to_update_field,
+ const char* hexdump_prefix);
+ int setStringFieldAndResetState(
+ const char* value, char** to_update_field,
+ const char* hexdump_prefix);
+ int setStringKeyFieldAndResetState(
+ const char* value, char** to_update_field,
+ const char* hexdump_prefix);
+ int setByteArrayFieldAndResetState(
+ const uint8_t* value, const size_t value_len,
+ uint8_t** to_update_field, size_t* to_update_field_len,
+ const char* hexdump_prefix);
+ int setByteArrayKeyFieldAndResetState(
+ const uint8_t* value, const size_t value_len,
+ uint8_t** to_update_field, size_t* to_update_field_len,
+ const char* hexdump_prefix);
+ void setFastTransitionKeyMgmt(uint32_t &key_mgmt_mask);
+ void resetFastTransitionKeyMgmt(uint32_t &key_mgmt_mask);
+ ndk::ScopedAStatus setEapErpInternal(bool enable);
+
+ // Reference to the global wpa_struct. This is assumed to be valid
+ // for the lifetime of the process.
+ struct wpa_global* wpa_global_;
+ // Name of the iface this network belongs to.
+ const std::string ifname_;
+ // Id of the network this aidl object controls.
+ const int network_id_;
+ bool is_valid_;
+
+ DISALLOW_COPY_AND_ASSIGN(StaNetwork);
+};
+
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WPA_SUPPLICANT_AIDL_STA_NETWORK_H
diff --git a/wpa_supplicant/aidl/supplicant.cpp b/wpa_supplicant/aidl/supplicant.cpp
new file mode 100644
index 0000000..208491c
--- /dev/null
+++ b/wpa_supplicant/aidl/supplicant.cpp
@@ -0,0 +1,544 @@
+/*
+ * WPA Supplicant - Supplicant Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "aidl_manager.h"
+#include "aidl_return_util.h"
+#include "misc_utils.h"
+#include "supplicant.h"
+#include "p2p_iface.h"
+
+#include <android-base/file.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+namespace {
+
+// Pre-populated interface params for interfaces controlled by wpa_supplicant.
+// Note: This may differ for other OEM's. So, modify this accordingly.
+constexpr char kIfaceDriverName[] = "nl80211";
+constexpr char kStaIfaceConfPath[] =
+ "/data/vendor/wifi/wpa/wpa_supplicant.conf";
+static const char* kStaIfaceConfOverlayPaths[] = {
+ "/apex/com.android.wifi.hal/etc/wifi/wpa_supplicant_overlay.conf",
+ "/vendor/etc/wifi/wpa_supplicant_overlay.conf",
+};
+constexpr char kP2pIfaceConfPath[] =
+ "/data/vendor/wifi/wpa/p2p_supplicant.conf";
+static const char* kP2pIfaceConfOverlayPaths[] = {
+ "/apex/com.android.wifi.hal/etc/wifi/p2p_supplicant_overlay.conf",
+ "/vendor/etc/wifi/p2p_supplicant_overlay.conf",
+};
+// Migrate conf files for existing devices.
+static const char* kTemplateConfPaths[] = {
+ "/apex/com.android.wifi.hal/etc/wifi/wpa_supplicant.conf",
+ "/vendor/etc/wifi/wpa_supplicant.conf",
+ "/system/etc/wifi/wpa_supplicant.conf",
+};
+constexpr char kOldStaIfaceConfPath[] = "/data/misc/wifi/wpa_supplicant.conf";
+constexpr char kOldP2pIfaceConfPath[] = "/data/misc/wifi/p2p_supplicant.conf";
+constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
+
+const char* resolvePath(const char* paths[], size_t size)
+{
+ for (int i = 0; i < size; ++i) {
+ if (access(paths[i], R_OK) == 0) {
+ return paths[i];
+ }
+ }
+ return nullptr;
+}
+
+int copyFile(
+ const std::string& src_file_path, const std::string& dest_file_path)
+{
+ std::string file_contents;
+ if (!android::base::ReadFileToString(src_file_path, &file_contents)) {
+ wpa_printf(
+ MSG_ERROR, "Failed to read from %s. Errno: %s",
+ src_file_path.c_str(), strerror(errno));
+ return -1;
+ }
+ if (!android::base::WriteStringToFile(
+ file_contents, dest_file_path, kConfigFileMode, getuid(),
+ getgid())) {
+ wpa_printf(
+ MSG_ERROR, "Failed to write to %s. Errno: %s",
+ dest_file_path.c_str(), strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * Copy |src_file_path| to |dest_file_path| if it exists.
+ *
+ * Returns 1 if |src_file_path| does not exist or not accessible,
+ * Returns -1 if the copy fails.
+ * Returns 0 if the copy succeeds.
+ */
+int copyFileIfItExists(
+ const std::string& src_file_path, const std::string& dest_file_path)
+{
+ int ret = access(src_file_path.c_str(), R_OK);
+ // Sepolicy denial (2018+ device) will return EACCESS instead of ENOENT.
+ if ((ret != 0) && ((errno == ENOENT) || (errno == EACCES))) {
+ return 1;
+ }
+ ret = copyFile(src_file_path, dest_file_path);
+ if (ret != 0) {
+ wpa_printf(
+ MSG_ERROR, "Failed copying %s to %s.",
+ src_file_path.c_str(), dest_file_path.c_str());
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * Ensure that the specified config file pointed by |config_file_path| exists.
+ * a) If the |config_file_path| exists with the correct permissions, return.
+ * b) If the |config_file_path| does not exist, but |old_config_file_path|
+ * exists, copy over the contents of the |old_config_file_path| to
+ * |config_file_path|.
+ * c) If the |config_file_path| & |old_config_file_path|
+ * does not exists, copy over the contents of |template_config_file_path|.
+ */
+int ensureConfigFileExists(
+ const std::string& config_file_path,
+ const std::string& old_config_file_path)
+{
+ int ret = access(config_file_path.c_str(), R_OK | W_OK);
+ if (ret == 0) {
+ return 0;
+ }
+ if (errno == EACCES) {
+ ret = chmod(config_file_path.c_str(), kConfigFileMode);
+ if (ret == 0) {
+ return 0;
+ } else {
+ wpa_printf(
+ MSG_ERROR, "Cannot set RW to %s. Errno: %s",
+ config_file_path.c_str(), strerror(errno));
+ return -1;
+ }
+ } else if (errno != ENOENT) {
+ wpa_printf(
+ MSG_ERROR, "Cannot acces %s. Errno: %s",
+ config_file_path.c_str(), strerror(errno));
+ return -1;
+ }
+ ret = copyFileIfItExists(old_config_file_path, config_file_path);
+ if (ret == 0) {
+ wpa_printf(
+ MSG_INFO, "Migrated conf file from %s to %s",
+ old_config_file_path.c_str(), config_file_path.c_str());
+ unlink(old_config_file_path.c_str());
+ return 0;
+ } else if (ret == -1) {
+ unlink(config_file_path.c_str());
+ return -1;
+ }
+ const char* path =
+ resolvePath(kTemplateConfPaths, sizeof(kTemplateConfPaths));
+ if (path != nullptr) {
+ ret = copyFileIfItExists(path, config_file_path);
+ if (ret == 0) {
+ wpa_printf(
+ MSG_INFO, "Copied template conf file from %s to %s",
+ path, config_file_path.c_str());
+ return 0;
+ } else if (ret == -1) {
+ unlink(config_file_path.c_str());
+ return -1;
+ }
+ }
+ // Did not create the conf file.
+ return -1;
+}
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+using aidl_return_util::validateAndCall;
+using misc_utils::createStatus;
+using misc_utils::createStatusWithMsg;
+
+Supplicant::Supplicant(struct wpa_global* global) : wpa_global_(global) {}
+bool Supplicant::isValid()
+{
+ // This top level object cannot be invalidated.
+ return true;
+}
+
+::ndk::ScopedAStatus Supplicant::addP2pInterface(
+ const std::string& in_name,
+ std::shared_ptr<ISupplicantP2pIface>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &Supplicant::addP2pInterfaceInternal, _aidl_return, in_name);
+}
+
+::ndk::ScopedAStatus Supplicant::addStaInterface(
+ const std::string& in_name,
+ std::shared_ptr<ISupplicantStaIface>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &Supplicant::addStaInterfaceInternal, _aidl_return, in_name);
+}
+
+::ndk::ScopedAStatus Supplicant::removeInterface(
+ const IfaceInfo& in_ifaceInfo)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &Supplicant::removeInterfaceInternal, in_ifaceInfo);
+}
+
+::ndk::ScopedAStatus Supplicant::getP2pInterface(
+ const std::string& in_name,
+ std::shared_ptr<ISupplicantP2pIface>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &Supplicant::getP2pInterfaceInternal, _aidl_return, in_name);
+}
+
+::ndk::ScopedAStatus Supplicant::getStaInterface(
+ const std::string& in_name,
+ std::shared_ptr<ISupplicantStaIface>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &Supplicant::getStaInterfaceInternal, _aidl_return, in_name);
+}
+
+::ndk::ScopedAStatus Supplicant::listInterfaces(
+ std::vector<IfaceInfo>* _aidl_return)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &Supplicant::listInterfacesInternal, _aidl_return);
+}
+
+::ndk::ScopedAStatus Supplicant::registerCallback(
+ const std::shared_ptr<ISupplicantCallback>& in_callback)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &Supplicant::registerCallbackInternal, in_callback);
+}
+
+::ndk::ScopedAStatus Supplicant::setDebugParams(
+ DebugLevel in_level, bool in_showTimestamp,
+ bool in_showKeys)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &Supplicant::setDebugParamsInternal, in_level,
+ in_showTimestamp, in_showKeys);
+}
+
+::ndk::ScopedAStatus Supplicant::setConcurrencyPriority(
+ IfaceType in_type)
+{
+ return validateAndCall(
+ this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+ &Supplicant::setConcurrencyPriorityInternal, in_type);
+}
+
+::ndk::ScopedAStatus Supplicant::getDebugLevel(DebugLevel* _aidl_return)
+{
+ *_aidl_return = static_cast<DebugLevel>(wpa_debug_level);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Supplicant::isDebugShowTimestampEnabled(bool* _aidl_return)
+{
+ *_aidl_return = ((wpa_debug_timestamp != 0) ? true : false);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Supplicant::isDebugShowKeysEnabled(bool* _aidl_return)
+{
+ *_aidl_return = ((wpa_debug_show_keys != 0) ? true : false);
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Supplicant::terminate()
+{
+ wpa_printf(MSG_INFO, "Terminating...");
+ wpa_supplicant_terminate_proc(wpa_global_);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Supplicant::addP2pDevInterface(struct wpa_interface iface_params)
+{
+ char primary_ifname[IFNAMSIZ];
+ u32 primary_ifname_len =
+ strlen(iface_params.ifname) - strlen(P2P_MGMT_DEVICE_PREFIX);
+
+ if(primary_ifname_len > IFNAMSIZ) {
+ wpa_printf(MSG_DEBUG, "%s, Invalid primary iface name ", __FUNCTION__);
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+
+ strncpy(primary_ifname, iface_params.ifname +
+ strlen(P2P_MGMT_DEVICE_PREFIX), primary_ifname_len);
+ wpa_printf(MSG_DEBUG, "%s, Initialize p2p-dev-wlan0 iface with"
+ "primary_iface = %s", __FUNCTION__, primary_ifname);
+ struct wpa_supplicant* wpa_s =
+ wpa_supplicant_get_iface(wpa_global_, primary_ifname);
+ if (!wpa_s) {
+ wpa_printf(MSG_DEBUG, "%s,NULL wpa_s for wlan0", __FUNCTION__);
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+ }
+ if (wpas_p2p_add_p2pdev_interface(
+ wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
+ wpa_printf(MSG_INFO,
+ "Failed to enable P2P Device");
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::shared_ptr<ISupplicantP2pIface>, ndk::ScopedAStatus>
+Supplicant::addP2pInterfaceInternal(const std::string& name)
+{
+ std::shared_ptr<ISupplicantP2pIface> iface;
+
+ // Check if required |ifname| argument is empty.
+ if (name.empty()) {
+ return {nullptr, createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID)};
+ }
+ // Try to get the wpa_supplicant record for this iface, return
+ // the iface object with the appropriate status code if it exists.
+ ndk::ScopedAStatus status;
+ std::tie(iface, status) = getP2pInterfaceInternal(name);
+ if (status.isOk()) {
+ wpa_printf(MSG_INFO, "Iface already exists, return existing");
+ return {iface, ndk::ScopedAStatus::ok()};
+ }
+
+ struct wpa_interface iface_params = {};
+ iface_params.driver = kIfaceDriverName;
+ if (ensureConfigFileExists(
+ kP2pIfaceConfPath, kOldP2pIfaceConfPath) != 0) {
+ wpa_printf(
+ MSG_ERROR, "Conf file does not exists: %s",
+ kP2pIfaceConfPath);
+ return {nullptr, createStatusWithMsg(
+ SupplicantStatusCode::FAILURE_UNKNOWN, "Conf file does not exist")};
+ }
+ iface_params.confname = kP2pIfaceConfPath;
+ const char* path = resolvePath(
+ kP2pIfaceConfOverlayPaths,
+ sizeof(kP2pIfaceConfOverlayPaths));
+ if (path != nullptr) {
+ iface_params.confanother = path;
+ }
+
+ iface_params.ifname = name.c_str();
+ if (strncmp(iface_params.ifname, P2P_MGMT_DEVICE_PREFIX,
+ strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
+ status = addP2pDevInterface(iface_params);
+ if (!status.isOk()) {
+ return {iface, createStatus(static_cast<SupplicantStatusCode>(
+ status.getServiceSpecificError()))};
+ }
+ } else {
+ struct wpa_supplicant* wpa_s =
+ wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
+ if (!wpa_s) {
+ return {nullptr, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ // Request the current scan results from the driver and update
+ // the local BSS list wpa_s->bss. This is to avoid a full scan
+ // while processing the connect request on newly created interface.
+ wpa_supplicant_update_scan_results(wpa_s);
+ }
+ // The supplicant core creates a corresponding aidl object via
+ // AidlManager when |wpa_supplicant_add_iface| is called.
+ return getP2pInterfaceInternal(name);
+}
+
+std::pair<std::shared_ptr<ISupplicantStaIface>, ndk::ScopedAStatus>
+Supplicant::addStaInterfaceInternal(const std::string& name)
+{
+ std::shared_ptr<ISupplicantStaIface> iface;
+
+ // Check if required |ifname| argument is empty.
+ if (name.empty()) {
+ return {nullptr, createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID)};
+ }
+ // Try to get the wpa_supplicant record for this iface, return
+ // the iface object with the appropriate status code if it exists.
+ ndk::ScopedAStatus status;
+ std::tie(iface, status) = getStaInterfaceInternal(name);
+ if (status.isOk()) {
+ wpa_printf(MSG_INFO, "Iface already exists, return existing");
+ return {iface, ndk::ScopedAStatus::ok()};
+ }
+
+ struct wpa_interface iface_params = {};
+ iface_params.driver = kIfaceDriverName;
+ if (ensureConfigFileExists(
+ kStaIfaceConfPath, kOldStaIfaceConfPath) != 0) {
+ wpa_printf(
+ MSG_ERROR, "Conf file does not exists: %s",
+ kStaIfaceConfPath);
+ return {nullptr, createStatusWithMsg(
+ SupplicantStatusCode::FAILURE_UNKNOWN, "Conf file does not exist")};
+ }
+ iface_params.confname = kStaIfaceConfPath;
+ const char* path = resolvePath(
+ kStaIfaceConfOverlayPaths,
+ sizeof(kStaIfaceConfOverlayPaths));
+ if (path != nullptr) {
+ iface_params.confanother = path;
+ }
+
+ iface_params.ifname = name.c_str();
+ if (strncmp(iface_params.ifname, P2P_MGMT_DEVICE_PREFIX,
+ strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
+ status = addP2pDevInterface(iface_params);
+ if (!status.isOk()) {
+ return {iface, createStatus(static_cast<SupplicantStatusCode>(
+ status.getServiceSpecificError()))};
+ }
+ } else {
+ struct wpa_supplicant* wpa_s =
+ wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
+ if (!wpa_s) {
+ return {nullptr, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ // Request the current scan results from the driver and update
+ // the local BSS list wpa_s->bss. This is to avoid a full scan
+ // while processing the connect request on newly created interface.
+ wpa_supplicant_update_scan_results(wpa_s);
+ }
+ // The supplicant core creates a corresponding aidl object via
+ // AidlManager when |wpa_supplicant_add_iface| is called.
+ return getStaInterfaceInternal(name);
+}
+
+ndk::ScopedAStatus Supplicant::removeInterfaceInternal(
+ const IfaceInfo& iface_info)
+{
+ struct wpa_supplicant* wpa_s =
+ wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
+ if (!wpa_s) {
+ return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+ }
+ if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::shared_ptr<ISupplicantP2pIface>, ndk::ScopedAStatus>
+Supplicant::getP2pInterfaceInternal(const std::string& name)
+{
+ struct wpa_supplicant* wpa_s =
+ wpa_supplicant_get_iface(wpa_global_, name.c_str());
+ if (!wpa_s) {
+ return {nullptr, createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN)};
+ }
+ AidlManager* aidl_manager = AidlManager::getInstance();
+ std::shared_ptr<ISupplicantP2pIface> iface;
+ if (!aidl_manager ||
+ aidl_manager->getP2pIfaceAidlObjectByIfname(
+ wpa_s->ifname, &iface)) {
+ return {iface, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ // Set this flag true here, since there is no AIDL initialize
+ // method for the p2p config, and the supplicant interface is
+ // not ready when the p2p iface is created.
+ wpa_s->conf->persistent_reconnect = true;
+ return {iface, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::shared_ptr<ISupplicantStaIface>, ndk::ScopedAStatus>
+Supplicant::getStaInterfaceInternal(const std::string& name)
+{
+ struct wpa_supplicant* wpa_s =
+ wpa_supplicant_get_iface(wpa_global_, name.c_str());
+ if (!wpa_s) {
+ return {nullptr, createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN)};
+ }
+ AidlManager* aidl_manager = AidlManager::getInstance();
+ std::shared_ptr<ISupplicantStaIface> iface;
+ if (!aidl_manager ||
+ aidl_manager->getStaIfaceAidlObjectByIfname(
+ wpa_s->ifname, &iface)) {
+ return {iface, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+ }
+ return {iface, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<IfaceInfo>, ndk::ScopedAStatus>
+Supplicant::listInterfacesInternal()
+{
+ std::vector<IfaceInfo> ifaces;
+ for (struct wpa_supplicant* wpa_s = wpa_global_->ifaces; wpa_s;
+ wpa_s = wpa_s->next) {
+ if (wpa_s->global->p2p_init_wpa_s == wpa_s) {
+ ifaces.emplace_back(IfaceInfo{
+ IfaceType::P2P, wpa_s->ifname});
+ } else {
+ ifaces.emplace_back(IfaceInfo{
+ IfaceType::STA, wpa_s->ifname});
+ }
+ }
+ return {std::move(ifaces), ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus Supplicant::registerCallbackInternal(
+ const std::shared_ptr<ISupplicantCallback>& callback)
+{
+ AidlManager* aidl_manager = AidlManager::getInstance();
+ if (!aidl_manager ||
+ aidl_manager->addSupplicantCallbackAidlObject(callback)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Supplicant::setDebugParamsInternal(
+ DebugLevel level, bool show_timestamp, bool show_keys)
+{
+ if (wpa_supplicant_set_debug_params(
+ wpa_global_, static_cast<uint32_t>(level), show_timestamp,
+ show_keys)) {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Supplicant::setConcurrencyPriorityInternal(IfaceType type)
+{
+ if (type == IfaceType::STA) {
+ wpa_global_->conc_pref =
+ wpa_global::wpa_conc_pref::WPA_CONC_PREF_STA;
+ } else if (type == IfaceType::P2P) {
+ wpa_global_->conc_pref =
+ wpa_global::wpa_conc_pref::WPA_CONC_PREF_P2P;
+ } else {
+ return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wpa_supplicant/aidl/supplicant.h b/wpa_supplicant/aidl/supplicant.h
new file mode 100644
index 0000000..cbe9a67
--- /dev/null
+++ b/wpa_supplicant/aidl/supplicant.h
@@ -0,0 +1,111 @@
+/*
+ * WPA Supplicant - Supplicant Aidl interface
+ * Copyright (c) 2021, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_AIDL_SUPPLICANT_H
+#define WPA_SUPPLICANT_AIDL_SUPPLICANT_H
+
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicant.h>
+#include <aidl/android/hardware/wifi/supplicant/DebugLevel.h>
+#include <aidl/android/hardware/wifi/supplicant/IfaceInfo.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.h>
+#include <aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.h>
+
+#include <android-base/macros.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "utils/wpa_debug.h"
+#include "wpa_supplicant_i.h"
+#include "scan.h"
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+
+/**
+ * Implementation of the supplicant aidl object. This aidl
+ * object is used core for global control operations on
+ * wpa_supplicant.
+ */
+class Supplicant : public BnSupplicant
+{
+public:
+ Supplicant(struct wpa_global* global);
+ ~Supplicant() override = default;
+ bool isValid();
+
+ // Aidl methods exposed.
+ ::ndk::ScopedAStatus addP2pInterface(
+ const std::string& in_name,
+ std::shared_ptr<ISupplicantP2pIface>* _aidl_return) override;
+ ::ndk::ScopedAStatus addStaInterface(
+ const std::string& in_name,
+ std::shared_ptr<ISupplicantStaIface>* _aidl_return) override;
+ ::ndk::ScopedAStatus removeInterface(
+ const IfaceInfo& in_ifaceInfo) override;
+ ::ndk::ScopedAStatus getP2pInterface(
+ const std::string& in_name,
+ std::shared_ptr<ISupplicantP2pIface>* _aidl_return) override;
+ ::ndk::ScopedAStatus getStaInterface(
+ const std::string& in_name,
+ std::shared_ptr<ISupplicantStaIface>* _aidl_return) override;
+ ::ndk::ScopedAStatus listInterfaces(
+ std::vector<IfaceInfo>* _aidl_return) override;
+ ::ndk::ScopedAStatus registerCallback(
+ const std::shared_ptr<ISupplicantCallback>& in_callback) override;
+ ::ndk::ScopedAStatus setDebugParams(
+ DebugLevel in_level, bool in_showTimestamp, bool in_showKeys) override;
+ ::ndk::ScopedAStatus getDebugLevel(DebugLevel* _aidl_return) override;
+ ::ndk::ScopedAStatus isDebugShowTimestampEnabled(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus isDebugShowKeysEnabled(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus setConcurrencyPriority(IfaceType in_type) override;
+ ::ndk::ScopedAStatus terminate() override;
+
+private:
+ // Corresponding worker functions for the AIDL methods.
+ std::pair<std::shared_ptr<ISupplicantP2pIface>, ndk::ScopedAStatus>
+ addP2pInterfaceInternal(const std::string& name);
+ std::pair<std::shared_ptr<ISupplicantStaIface>, ndk::ScopedAStatus>
+ addStaInterfaceInternal(const std::string& name);
+ std::pair<std::shared_ptr<ISupplicantP2pIface>, ndk::ScopedAStatus>
+ getP2pInterfaceInternal(const std::string& name);
+ std::pair<std::shared_ptr<ISupplicantStaIface>, ndk::ScopedAStatus>
+ getStaInterfaceInternal(const std::string& name);
+
+ ndk::ScopedAStatus removeInterfaceInternal(const IfaceInfo& iface_info);
+ std::pair<std::vector<IfaceInfo>, ndk::ScopedAStatus> listInterfacesInternal();
+ ndk::ScopedAStatus registerCallbackInternal(
+ const std::shared_ptr<ISupplicantCallback>& callback);
+ ndk::ScopedAStatus setDebugParamsInternal(
+ DebugLevel level, bool show_timestamp, bool show_keys);
+ ndk::ScopedAStatus setConcurrencyPriorityInternal(IfaceType type);
+ ndk::ScopedAStatus addP2pDevInterface(struct wpa_interface iface_params);
+
+ // Raw pointer to the global structure maintained by the core.
+ struct wpa_global* wpa_global_;
+ // Driver name to be used for creating interfaces.
+ static const char kDriverName[];
+ // wpa_supplicant.conf file location on the device.
+ static const char kConfigFilePath[];
+
+ DISALLOW_COPY_AND_ASSIGN(Supplicant);
+};
+
+} // namespace supplicant
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WPA_SUPPLICANT_AIDL_SUPPLICANT_H