/* * 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 pending_join_scan_callback = NULL; std::function 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; using aidl::android::hardware::wifi::supplicant::P2pFrameTypeMask; 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& ssid) { if (ssid.size() == 0 || ssid.size() > static_cast(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(ISupplicantStaNetwork:: PSK_PASSPHRASE_MIN_LEN_IN_BYTES) || psk.size() > static_cast(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& 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& 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; } static bool is6GhzAllowed(struct wpa_supplicant *wpa_s) { if (!wpa_s->global->p2p) return false; return wpa_s->global->p2p->allow_6ghz; } int joinGroup( struct wpa_supplicant* wpa_s, uint8_t *group_owner_bssid, const std::vector& 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, is6GhzAllowed(wpa_s))) { 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 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); } } static void updateP2pVendorElem(struct wpa_supplicant* wpa_s, enum wpa_vendor_elem_frame frameType, const std::vector& vendorElemBytes) { wpa_printf(MSG_INFO, "Set vendor elements to frames %d", frameType); struct wpa_supplicant* vendor_elem_wpa_s = wpas_vendor_elem(wpa_s, frameType); if (vendor_elem_wpa_s->vendor_elem[frameType]) { wpabuf_free(vendor_elem_wpa_s->vendor_elem[frameType]); vendor_elem_wpa_s->vendor_elem[frameType] = NULL; } if (vendorElemBytes.size() > 0) { vendor_elem_wpa_s->vendor_elem[frameType] = wpabuf_alloc_copy(vendorElemBytes.data(), vendorElemBytes.size()); } wpas_vendor_elem_update(vendor_elem_wpa_s); } uint32_t convertWpaP2pFrameTypeToHalP2pFrameTypeBit(int frameType) { switch (frameType) { case VENDOR_ELEM_PROBE_REQ_P2P: return static_cast(P2pFrameTypeMask::P2P_FRAME_PROBE_REQ_P2P); case VENDOR_ELEM_PROBE_RESP_P2P: return static_cast(P2pFrameTypeMask::P2P_FRAME_PROBE_RESP_P2P); case VENDOR_ELEM_PROBE_RESP_P2P_GO: return static_cast(P2pFrameTypeMask::P2P_FRAME_PROBE_RESP_P2P_GO); case VENDOR_ELEM_BEACON_P2P_GO: return static_cast(P2pFrameTypeMask::P2P_FRAME_BEACON_P2P_GO); case VENDOR_ELEM_P2P_PD_REQ: return static_cast(P2pFrameTypeMask::P2P_FRAME_P2P_PD_REQ); case VENDOR_ELEM_P2P_PD_RESP: return static_cast(P2pFrameTypeMask::P2P_FRAME_P2P_PD_RESP); case VENDOR_ELEM_P2P_GO_NEG_REQ: return static_cast(P2pFrameTypeMask::P2P_FRAME_P2P_GO_NEG_REQ); case VENDOR_ELEM_P2P_GO_NEG_RESP: return static_cast(P2pFrameTypeMask::P2P_FRAME_P2P_GO_NEG_RESP); case VENDOR_ELEM_P2P_GO_NEG_CONF: return static_cast(P2pFrameTypeMask::P2P_FRAME_P2P_GO_NEG_CONF); case VENDOR_ELEM_P2P_INV_REQ: return static_cast(P2pFrameTypeMask::P2P_FRAME_P2P_INV_REQ); case VENDOR_ELEM_P2P_INV_RESP: return static_cast(P2pFrameTypeMask::P2P_FRAME_P2P_INV_RESP); case VENDOR_ELEM_P2P_ASSOC_REQ: return static_cast(P2pFrameTypeMask::P2P_FRAME_P2P_ASSOC_REQ); case VENDOR_ELEM_P2P_ASSOC_RESP: return static_cast(P2pFrameTypeMask::P2P_FRAME_P2P_ASSOC_RESP); } return 0; } } // 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* _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* _aidl_return) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::getNetworkInternal, _aidl_return, in_id); } ::ndk::ScopedAStatus P2pIface::listNetworks( std::vector* _aidl_return) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::listNetworksInternal, _aidl_return); } ::ndk::ScopedAStatus P2pIface::registerCallback( const std::shared_ptr& in_callback) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::registerCallbackInternal, in_callback); } ::ndk::ScopedAStatus P2pIface::getDeviceAddress( std::vector* _aidl_return) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::getDeviceAddressInternal, _aidl_return); } ::ndk::ScopedAStatus P2pIface::setSsidPostfix( const std::vector& 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& 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& 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& in_ssid, const std::string& in_pskPassphrase, bool in_persistent, int32_t in_freq, const std::vector& 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& 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& in_goDeviceAddress, const std::vector& 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& 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& in_ranges) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::setDisallowedFrequenciesInternal, in_ranges); } ::ndk::ScopedAStatus P2pIface::getSsid( const std::vector& in_peerAddress, std::vector* _aidl_return) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::getSsidInternal, _aidl_return, in_peerAddress); } ::ndk::ScopedAStatus P2pIface::getGroupCapability( const std::vector& 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& in_query, const std::vector& in_response) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::addBonjourServiceInternal, in_query, in_response); } ::ndk::ScopedAStatus P2pIface::removeBonjourService( const std::vector& 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& in_peerAddress, const std::vector& 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& 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& 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& 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& in_info) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::setWfdDeviceInfoInternal, in_info); } ::ndk::ScopedAStatus P2pIface::createNfcHandoverRequestMessage( std::vector* _aidl_return) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::createNfcHandoverRequestMessageInternal, _aidl_return); } ::ndk::ScopedAStatus P2pIface::createNfcHandoverSelectMessage( std::vector* _aidl_return) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::createNfcHandoverSelectMessageInternal, _aidl_return); } ::ndk::ScopedAStatus P2pIface::reportNfcHandoverResponse( const std::vector& in_request) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::reportNfcHandoverResponseInternal, in_request); } ::ndk::ScopedAStatus P2pIface::reportNfcHandoverInitiation( const std::vector& 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& in_info) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::setWfdR2DeviceInfoInternal, in_info); } ::ndk::ScopedAStatus P2pIface::removeClient( const std::vector& peer_address, bool isLegacyClient) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::removeClientInternal, peer_address, isLegacyClient); } ::ndk::ScopedAStatus P2pIface::findOnSocialChannels( int32_t in_timeoutInSec) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::findOnSocialChannelsInternal, in_timeoutInSec); } ::ndk::ScopedAStatus P2pIface::findOnSpecificFrequency( int32_t in_freq, int32_t in_timeoutInSec) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::findOnSpecificFrequencyInternal, in_freq, in_timeoutInSec); } ::ndk::ScopedAStatus P2pIface::setVendorElements( P2pFrameTypeMask in_frameTypeMask, const std::vector& in_vendorElemBytes) { return validateAndCall( this, SupplicantStatusCode::FAILURE_IFACE_INVALID, &P2pIface::setVendorElementsInternal, in_frameTypeMask, in_vendorElemBytes); } std::pair P2pIface::getNameInternal() { return {ifname_, ndk::ScopedAStatus::ok()}; } std::pair P2pIface::getTypeInternal() { return {IfaceType::P2P, ndk::ScopedAStatus::ok()}; } std::pair, ndk::ScopedAStatus> P2pIface::addNetworkInternal() { std::shared_ptr 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, ndk::ScopedAStatus> P2pIface::getNetworkInternal(int32_t id) { std::shared_ptr 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, ndk::ScopedAStatus> P2pIface::listNetworksInternal() { std::vector 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& 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, ndk::ScopedAStatus> P2pIface::getDeviceAddressInternal() { struct wpa_supplicant* wpa_s = retrieveIfacePtr(); std::vector 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& 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, is6GhzAllowed(wpa_s))) { 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 P2pIface::connectInternal( const std::vector& 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)}; } if (peer_address.size() != ETH_ALEN) { 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, is6GhzAllowed(wpa_s)); 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& peer_address, WpsProvisionMethod provision_method) { struct wpa_supplicant* wpa_s = retrieveIfacePtr(); p2ps_provision* prov_param; const char* config_method_str = nullptr; if (peer_address.size() != ETH_ALEN) { return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN); } 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& 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 (peer_address.size() != ETH_ALEN) { return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN); } 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& go_device_address, const std::vector& peer_address) { struct wpa_supplicant* wpa_s = retrieveIfacePtr(); if (go_device_address.size() != ETH_ALEN || peer_address.size() != ETH_ALEN) { return {createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)}; } if (wpas_p2p_invite_group( wpa_s, group_ifname.c_str(), peer_address.data(), go_device_address.data(), is6GhzAllowed(wpa_s))) { return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN); } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus P2pIface::reinvokeInternal( int32_t persistent_network_id, const std::vector& 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 (peer_address.size() != ETH_ALEN) { return {createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)}; } if (wpas_p2p_invite( wpa_s, peer_address.data(), ssid, NULL, 0, 0, ht40, vht, CHANWIDTH_USE_HT, 0, he, 0, is6GhzAllowed(wpa_s))) { 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& 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( 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, ndk::ScopedAStatus> P2pIface::getSsidInternal( const std::vector& peer_address) { struct wpa_supplicant* wpa_s = retrieveIfacePtr(); if (peer_address.size() != ETH_ALEN) { return {std::vector(), createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)}; } const struct p2p_peer_info* info = p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0); if (!info) { return {std::vector(), createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)}; } const struct p2p_device* dev = reinterpret_cast( (reinterpret_cast(info)) - offsetof(struct p2p_device, info)); std::vector 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 P2pIface::getGroupCapabilityInternal( const std::vector& peer_address) { struct wpa_supplicant* wpa_s = retrieveIfacePtr(); if (peer_address.size() != ETH_ALEN) { return {static_cast(0), createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)}; } const struct p2p_peer_info* info = p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0); if (!info) { return {static_cast(0), createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)}; } return {static_cast(info->group_capab), ndk::ScopedAStatus::ok()}; } ndk::ScopedAStatus P2pIface::addBonjourServiceInternal( const std::vector& query, const std::vector& 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& 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 P2pIface::requestServiceDiscoveryInternal( const std::vector& peer_address, const std::vector& query) { struct wpa_supplicant* wpa_s = retrieveIfacePtr(); auto query_buf = misc_utils::convertVectorToWpaBuf(query); if (!query_buf) { return {0, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)}; } if (peer_address.size() != ETH_ALEN) { 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 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& bssid) { struct wpa_supplicant* wpa_group_s = retrieveGroupIfacePtr(group_ifname); if (!wpa_group_s) { return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN); } if (bssid.size() != ETH_ALEN) { return createStatus(SupplicantStatusCode::FAILURE_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 P2pIface::startWpsPinDisplayInternal( const std::string& group_ifname, const std::vector& bssid) { struct wpa_supplicant* wpa_group_s = retrieveGroupIfacePtr(group_ifname); if (!wpa_group_s) { return {"", createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN)}; } if (bssid.size() != ETH_ALEN) { return {"", createStatus(SupplicantStatusCode::FAILURE_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& type) { std::array type_arr; if (type.size() != 8) { return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN); } 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(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& info) { struct wpa_supplicant* wpa_s = retrieveIfacePtr(); std::vector 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 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, 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(), createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)}; } return {misc_utils::convertWpaBufToVector(buf.get()), ndk::ScopedAStatus::ok()}; } std::pair, 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(), createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)}; } return {misc_utils::convertWpaBufToVector(buf.get()), ndk::ScopedAStatus::ok()}; } ndk::ScopedAStatus P2pIface::reportNfcHandoverResponseInternal( const std::vector& request) { struct wpa_supplicant* wpa_s = retrieveIfacePtr(); auto req = misc_utils::convertVectorToWpaBuf(request); auto sel = misc_utils::convertVectorToWpaBuf(std::vector{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& select) { struct wpa_supplicant* wpa_s = retrieveIfacePtr(); auto req = misc_utils::convertVectorToWpaBuf(std::vector{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, is6GhzAllowed(wpa_s))) { 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, is6GhzAllowed(wpa_s))) { return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN); } else { return ndk::ScopedAStatus::ok(); } } return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN); } ndk::ScopedAStatus P2pIface::addGroupWithConfigInternal( const std::vector& ssid, const std::string& passphrase, bool persistent, uint32_t freq, const std::vector& 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, is6GhzAllowed(wpa_s))) { 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 (peer_address.size() != ETH_ALEN) { return createStatusWithMsg(SupplicantStatusCode::FAILURE_ARGS_INVALID, "Peer address is invalid."); } 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", wpa_ssid_txt(ssid.data(), ssid.size())); 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_ARGS_INVALID, "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 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& info) { struct wpa_supplicant* wpa_s = retrieveIfacePtr(); uint32_t wfd_r2_device_info_hex_len = info.size() * 2 + 1; std::vector 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 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(); } ndk::ScopedAStatus P2pIface::removeClientInternal( const std::vector& peer_address, bool isLegacyClient) { struct wpa_supplicant* wpa_s = retrieveIfacePtr(); if (peer_address.size() != ETH_ALEN) { return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN); } wpas_p2p_remove_client(wpa_s, peer_address.data(), isLegacyClient? 1 : 0); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus P2pIface::findOnSocialChannelsInternal(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_ONLY_SOCIAL, 0, nullptr, nullptr, search_delay, 0, nullptr, 0, is6GhzAllowed(wpa_s))) { return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN); } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus P2pIface::findOnSpecificFrequencyInternal( uint32_t freq, 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, freq, is6GhzAllowed(wpa_s))) { return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN); } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus P2pIface::setVendorElementsInternal( P2pFrameTypeMask frameTypeMask, const std::vector& vendorElemBytes) { struct wpa_supplicant* wpa_s = retrieveIfacePtr(); for (int i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) { uint32_t bit = convertWpaP2pFrameTypeToHalP2pFrameTypeBit(i); if (0 == bit) continue; if (static_cast(frameTypeMask) & bit) { updateP2pVendorElem(wpa_s, (enum wpa_vendor_elem_frame) i, vendorElemBytes); } } 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