/* * hidl interface for wpa_supplicant daemon * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com> * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #include <algorithm> #include <regex> #include "hidl_manager.h" #include "misc_utils.h" extern "C" { #include "scan.h" #include "src/eap_common/eap_sim_common.h" } namespace { using android::hardware::hidl_array; using namespace android::hardware::wifi::supplicant::V1_2; constexpr uint8_t kWfdDeviceInfoLen = 6; // 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; constexpr u8 kZeroBssid[6] = {0, 0, 0, 0, 0, 0}; /** * 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 hidl object reference. */ template <class CallbackType> int registerForDeathAndAddCallbackHidlObjectToList( const android::sp<CallbackType> &callback, const std::function<void(const android::sp<CallbackType> &)> &on_hidl_died_fctor, std::vector<android::sp<CallbackType>> &callback_list) { #if 0 // TODO(b/31632518): HIDL object death notifications. auto death_notifier = new CallbackObjectDeathNotifier<CallbackType>( callback, on_hidl_died_fctor); // Use the |callback.get()| as cookie so that we don't need to // store a reference to this |CallbackObjectDeathNotifier| instance // to use in |unlinkToDeath| later. // NOTE: This may cause an immediate callback if the object is already // dead, so add it to the list before we register for callback! if (android::hardware::IInterface::asBinder(callback)->linkToDeath( death_notifier, callback.get()) != android::OK) { wpa_printf( MSG_ERROR, "Error registering for death notification for " "supplicant callback object"); callback_list.erase( std::remove( callback_list.begin(), callback_list.end(), callback), callback_list.end()); return 1; } #endif // TODO(b/31632518): HIDL object death notifications. callback_list.push_back(callback); return 0; } template <class ObjectType> int addHidlObjectToMap( const std::string &key, const android::sp<ObjectType> object, std::map<const std::string, android::sp<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 removeHidlObjectFromMap( const std::string &key, std::map<const std::string, android::sp<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 addIfaceCallbackHidlObjectToMap( const std::string &ifname, const android::sp<CallbackType> &callback, const std::function<void(const android::sp<CallbackType> &)> &on_hidl_died_fctor, std::map<const std::string, std::vector<android::sp<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 registerForDeathAndAddCallbackHidlObjectToList<CallbackType>( callback, on_hidl_died_fctor, iface_callback_list); } template <class CallbackType> int addNetworkCallbackHidlObjectToMap( const std::string &ifname, int network_id, const android::sp<CallbackType> &callback, const std::function<void(const android::sp<CallbackType> &)> &on_hidl_died_fctor, std::map<const std::string, std::vector<android::sp<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 registerForDeathAndAddCallbackHidlObjectToList<CallbackType>( callback, on_hidl_died_fctor, network_callback_list); } template <class CallbackType> int removeAllIfaceCallbackHidlObjectsFromMap( const std::string &ifname, std::map<const std::string, std::vector<android::sp<CallbackType>>> &callbacks_map) { auto iface_callback_map_iter = callbacks_map.find(ifname); if (iface_callback_map_iter == callbacks_map.end()) return 1; #if 0 // TODO(b/31632518): HIDL object death notifications. const auto &iface_callback_list = iface_callback_map_iter->second; for (const auto &callback : iface_callback_list) { if (android::hardware::IInterface::asBinder(callback) ->unlinkToDeath(nullptr, callback.get()) != android::OK) { wpa_printf( MSG_ERROR, "Error deregistering for death notification for " "iface callback object"); } } #endif // TODO(b/31632518): HIDL object death notifications. callbacks_map.erase(iface_callback_map_iter); return 0; } template <class CallbackType> int removeAllNetworkCallbackHidlObjectsFromMap( const std::string &network_key, std::map<const std::string, std::vector<android::sp<CallbackType>>> &callbacks_map) { auto network_callback_map_iter = callbacks_map.find(network_key); if (network_callback_map_iter == callbacks_map.end()) return 1; #if 0 // TODO(b/31632518): HIDL object death notifications. const auto &network_callback_list = network_callback_map_iter->second; for (const auto &callback : network_callback_list) { if (android::hardware::IInterface::asBinder(callback) ->unlinkToDeath(nullptr, callback.get()) != android::OK) { wpa_printf( MSG_ERROR, "Error deregistering for death " "notification for " "network callback object"); } } #endif // TODO(b/31632518): HIDL object death notifications. callbacks_map.erase(network_callback_map_iter); return 0; } template <class CallbackType> void removeIfaceCallbackHidlObjectFromMap( const std::string &ifname, const android::sp<CallbackType> &callback, std::map<const std::string, std::vector<android::sp<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 removeNetworkCallbackHidlObjectFromMap( const std::string &ifname, int network_id, const android::sp<CallbackType> &callback, std::map<const std::string, std::vector<android::sp<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< android::hardware::Return<void>(android::sp<CallbackType>)> &method, const std::map<const std::string, std::vector<android::sp<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 HIDL iface callback"); } } } template <class CallbackTypeV1_0, class CallbackTypeV1_1> void callWithEachIfaceCallback_1_1( const std::string &ifname, const std::function< android::hardware::Return<void>(android::sp<CallbackTypeV1_1>)> &method, const std::map< const std::string, std::vector<android::sp<CallbackTypeV1_0>>> &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) { android::sp<CallbackTypeV1_1> callback_1_1 = CallbackTypeV1_1::castFrom(callback); if (callback_1_1 == nullptr) continue; if (!method(callback_1_1).isOk()) { wpa_printf( MSG_ERROR, "Failed to invoke HIDL iface callback"); } } } template <class CallbackTypeV1_0, class CallbackTypeV1_2> void callWithEachIfaceCallback_1_2( const std::string &ifname, const std::function< android::hardware::Return<void>(android::sp<CallbackTypeV1_2>)> &method, const std::map< const std::string, std::vector<android::sp<CallbackTypeV1_0>>> &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) { android::sp<CallbackTypeV1_2> callback_1_2 = CallbackTypeV1_2::castFrom(callback); if (callback_1_2 == nullptr) continue; if (!method(callback_1_2).isOk()) { wpa_printf( MSG_ERROR, "Failed to invoke HIDL iface callback"); } } } template <class CallbackType> void callWithEachNetworkCallback( const std::string &ifname, int network_id, const std::function< android::hardware::Return<void>(android::sp<CallbackType>)> &method, const std::map<const std::string, std::vector<android::sp<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 HIDL network callback"); } } } int parseGsmAuthNetworkRequest( const std::string ¶ms_str, std::vector<hidl_array<uint8_t, kGsmRandLenBytes>> *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++) { hidl_array<uint8_t, kGsmRandLenBytes> rand; const auto &match = matches[i]; WPA_ASSERT(match.size() >= 2 * rand.size()); if (hexstr2bin(match.str().c_str(), rand.data(), rand.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, hidl_array<uint8_t, kUmtsRandLenBytes> *out_rand, hidl_array<uint8_t, kUmtsAutnLenBytes> *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; } } // namespace namespace android { namespace hardware { namespace wifi { namespace supplicant { namespace V1_2 { namespace implementation { using namespace android::hardware::wifi::supplicant::V1_2; using V1_0::ISupplicantStaIfaceCallback; HidlManager *HidlManager::instance_ = NULL; HidlManager *HidlManager::getInstance() { if (!instance_) instance_ = new HidlManager(); return instance_; } void HidlManager::destroyInstance() { if (instance_) delete instance_; instance_ = NULL; } int HidlManager::registerHidlService(struct wpa_global *global) { // Create the main hidl service object and register it. supplicant_object_ = new Supplicant(global); if (supplicant_object_->registerAsService() != android::NO_ERROR) { return 1; } return 0; } /** * Register an interface to hidl manager. * * @param wpa_s |wpa_supplicant| struct corresponding to the interface. * * @return 0 on success, 1 on failure. */ int HidlManager::registerInterface(struct wpa_supplicant *wpa_s) { if (!wpa_s) return 1; if (isP2pIface(wpa_s)) { if (addHidlObjectToMap<P2pIface>( wpa_s->ifname, new P2pIface(wpa_s->global, wpa_s->ifname), p2p_iface_object_map_)) { wpa_printf( MSG_ERROR, "Failed to register P2P interface with HIDL " "control: %s", wpa_s->ifname); return 1; } p2p_iface_callbacks_map_[wpa_s->ifname] = std::vector<android::sp<ISupplicantP2pIfaceCallback>>(); } else { if (addHidlObjectToMap<StaIface>( wpa_s->ifname, new StaIface(wpa_s->global, wpa_s->ifname), sta_iface_object_map_)) { wpa_printf( MSG_ERROR, "Failed to register STA interface with HIDL " "control: %s", wpa_s->ifname); return 1; } sta_iface_callbacks_map_[wpa_s->ifname] = std::vector<android::sp<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"); } } } // Invoke the |onInterfaceCreated| method on all registered callbacks. callWithEachSupplicantCallback(std::bind( &ISupplicantCallback::onInterfaceCreated, std::placeholders::_1, wpa_s->ifname)); return 0; } /** * Unregister an interface from hidl manager. * * @param wpa_s |wpa_supplicant| struct corresponding to the interface. * * @return 0 on success, 1 on failure. */ int HidlManager::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 HIDL interface. bool success = !removeHidlObjectFromMap(wpa_s->ifname, p2p_iface_object_map_); if (success) { // assumed to be P2P success = !removeAllIfaceCallbackHidlObjectsFromMap( wpa_s->ifname, p2p_iface_callbacks_map_); } else { // assumed to be STA success = !removeHidlObjectFromMap( wpa_s->ifname, sta_iface_object_map_); if (success) { success = !removeAllIfaceCallbackHidlObjectsFromMap( wpa_s->ifname, sta_iface_callbacks_map_); } } if (!success) { wpa_printf( MSG_ERROR, "Failed to unregister interface with HIDL " "control: %s", wpa_s->ifname); return 1; } // Invoke the |onInterfaceRemoved| method on all registered callbacks. callWithEachSupplicantCallback(std::bind( &ISupplicantCallback::onInterfaceRemoved, std::placeholders::_1, wpa_s->ifname)); return 0; } /** * Register a network to hidl 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 HidlManager::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 (addHidlObjectToMap<P2pNetwork>( network_key, new P2pNetwork(wpa_s->global, wpa_s->ifname, ssid->id), p2p_network_object_map_)) { wpa_printf( MSG_ERROR, "Failed to register P2P network with HIDL " "control: %d", ssid->id); return 1; } p2p_network_callbacks_map_[network_key] = std::vector<android::sp<ISupplicantP2pNetworkCallback>>(); // Invoke the |onNetworkAdded| method on all registered // callbacks. callWithEachP2pIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onNetworkAdded, std::placeholders::_1, ssid->id)); } else { if (addHidlObjectToMap<StaNetwork>( network_key, new StaNetwork(wpa_s->global, wpa_s->ifname, ssid->id), sta_network_object_map_)) { wpa_printf( MSG_ERROR, "Failed to register STA network with HIDL " "control: %d", ssid->id); return 1; } sta_network_callbacks_map_[network_key] = std::vector<android::sp<ISupplicantStaNetworkCallback>>(); // Invoke the |onNetworkAdded| method on all registered // callbacks. callWithEachStaIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onNetworkAdded, std::placeholders::_1, ssid->id)); } return 0; } /** * Unregister a network from hidl 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 HidlManager::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 (removeHidlObjectFromMap( network_key, p2p_network_object_map_)) { wpa_printf( MSG_ERROR, "Failed to unregister P2P network with HIDL " "control: %d", ssid->id); return 1; } if (removeAllNetworkCallbackHidlObjectsFromMap( network_key, p2p_network_callbacks_map_)) return 1; // Invoke the |onNetworkRemoved| method on all registered // callbacks. callWithEachP2pIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onNetworkRemoved, std::placeholders::_1, ssid->id)); } else { if (removeHidlObjectFromMap( network_key, sta_network_object_map_)) { wpa_printf( MSG_ERROR, "Failed to unregister STA network with HIDL " "control: %d", ssid->id); return 1; } if (removeAllNetworkCallbackHidlObjectsFromMap( network_key, sta_network_callbacks_map_)) return 1; // Invoke the |onNetworkRemoved| method on all registered // callbacks. callWithEachStaIfaceCallback( 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 HidlManager::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 hidl_network_id = UINT32_MAX; std::vector<uint8_t> hidl_ssid; if (wpa_s->current_ssid) { hidl_network_id = wpa_s->current_ssid->id; hidl_ssid.assign( wpa_s->current_ssid->ssid, wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len); } 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 HIDL callback send the appropriate bssid. if (wpa_s->wpa_state <= WPA_ASSOCIATED) { bssid = wpa_s->pending_bssid; } else { bssid = wpa_s->bssid; } callWithEachStaIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onStateChanged, std::placeholders::_1, static_cast<ISupplicantStaIfaceCallback::State>( wpa_s->wpa_state), bssid, hidl_network_id, hidl_ssid)); 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 HidlManager::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( wpa_s->ifname, ssid->id, std::bind( &ISupplicantStaNetworkCallback:: onNetworkEapIdentityRequest, std::placeholders::_1)); return 0; } if (type == WPA_CTRL_REQ_SIM) { std::vector<hidl_array<uint8_t, 16>> gsm_rands; hidl_array<uint8_t, 16> umts_rand; hidl_array<uint8_t, 16> umts_autn; if (!parseGsmAuthNetworkRequest(param, &gsm_rands)) { ISupplicantStaNetworkCallback:: NetworkRequestEapSimGsmAuthParams hidl_params; hidl_params.rands = gsm_rands; callWithEachStaNetworkCallback( wpa_s->ifname, ssid->id, std::bind( &ISupplicantStaNetworkCallback:: onNetworkEapSimGsmAuthRequest, std::placeholders::_1, hidl_params)); return 0; } if (!parseUmtsAuthNetworkRequest( param, &umts_rand, &umts_autn)) { ISupplicantStaNetworkCallback:: NetworkRequestEapSimUmtsAuthParams hidl_params; hidl_params.rand = umts_rand; hidl_params.autn = umts_autn; callWithEachStaNetworkCallback( wpa_s->ifname, ssid->id, std::bind( &ISupplicantStaNetworkCallback:: onNetworkEapSimUmtsAuthRequest, std::placeholders::_1, hidl_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 HidlManager::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; ISupplicantStaIfaceCallback::AnqpData hidl_anqp_data; ISupplicantStaIfaceCallback::Hs20AnqpData hidl_hs20_anqp_data; if (std::string(result) == "SUCCESS") { hidl_anqp_data.venueName = misc_utils::convertWpaBufToVector(anqp->venue_name); hidl_anqp_data.roamingConsortium = misc_utils::convertWpaBufToVector(anqp->roaming_consortium); hidl_anqp_data.ipAddrTypeAvailability = misc_utils::convertWpaBufToVector( anqp->ip_addr_type_availability); hidl_anqp_data.naiRealm = misc_utils::convertWpaBufToVector(anqp->nai_realm); hidl_anqp_data.anqp3gppCellularNetwork = misc_utils::convertWpaBufToVector(anqp->anqp_3gpp); hidl_anqp_data.domainName = misc_utils::convertWpaBufToVector(anqp->domain_name); hidl_hs20_anqp_data.operatorFriendlyName = misc_utils::convertWpaBufToVector( anqp->hs20_operator_friendly_name); hidl_hs20_anqp_data.wanMetrics = misc_utils::convertWpaBufToVector(anqp->hs20_wan_metrics); hidl_hs20_anqp_data.connectionCapability = misc_utils::convertWpaBufToVector( anqp->hs20_connection_capability); hidl_hs20_anqp_data.osuProvidersList = misc_utils::convertWpaBufToVector( anqp->hs20_osu_providers_list); } callWithEachStaIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onAnqpQueryDone, std::placeholders::_1, bssid, hidl_anqp_data, hidl_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 HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onHs20IconQueryDone, std::placeholders::_1, 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 HidlManager::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; ISupplicantStaIfaceCallback::OsuMethod hidl_osu_method = {}; if (osu_method & 0x1) { hidl_osu_method = ISupplicantStaIfaceCallback::OsuMethod::OMA_DM; } else if (osu_method & 0x2) { hidl_osu_method = ISupplicantStaIfaceCallback::OsuMethod::SOAP_XML_SPP; } callWithEachStaIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onHs20SubscriptionRemediation, std::placeholders::_1, wpa_s->bssid, hidl_osu_method, url)); } /** * Notify all listeners about the reception of HS20 immient deauth * notification from the server. * * @param wpa_s |wpa_supplicant| struct corresponding to the interface. * @param code Deauth reason code sent from server. * @param reauth_delay Reauthentication delay in seconds sent from server. * @param url URL of the server. */ void HidlManager::notifyHs20RxDeauthImminentNotice( struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url) { if (!wpa_s || !url) return; if (sta_iface_object_map_.find(wpa_s->ifname) == sta_iface_object_map_.end()) return; callWithEachStaIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onHs20DeauthImminentNotice, std::placeholders::_1, wpa_s->bssid, code, reauth_delay, 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 HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onDisconnected, std::placeholders::_1, bssid, wpa_s->disconnect_reason < 0, static_cast<ISupplicantStaIfaceCallback::ReasonCode>( 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. */ void HidlManager::notifyAssocReject(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( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onAssociationRejected, std::placeholders::_1, bssid, static_cast<ISupplicantStaIfaceCallback::StatusCode>( wpa_s->assoc_status_code), wpa_s->assoc_timed_out == 1)); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onAuthenticationTimeout, std::placeholders::_1, bssid)); } void HidlManager::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; ISupplicantStaIfaceCallback::BssidChangeReason reason; if (is_zero_ether_addr(wpa_s->bssid) && !is_zero_ether_addr(wpa_s->pending_bssid)) { bssid = wpa_s->pending_bssid; reason = ISupplicantStaIfaceCallback::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 = ISupplicantStaIfaceCallback::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 = ISupplicantStaIfaceCallback::BssidChangeReason::DISASSOC; } else { wpa_printf(MSG_ERROR, "Unknown bssid change reason"); return; } callWithEachStaIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onBssidChanged, std::placeholders::_1, reason, bssid)); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onWpsEventFail, std::placeholders::_1, peer_macaddr, static_cast<ISupplicantStaIfaceCallback::WpsConfigError>( config_error), static_cast<ISupplicantStaIfaceCallback::WpsErrorIndication>( error_indication))); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onWpsEventSuccess, std::placeholders::_1)); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onWpsEventPbcOverlap, std::placeholders::_1)); } void HidlManager::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) { if (!wpa_s || !addr || !info) return; if (p2p_iface_object_map_.find(wpa_s->ifname) == p2p_iface_object_map_.end()) return; std::array<uint8_t, kWfdDeviceInfoLen> hidl_peer_wfd_device_info{}; 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( hidl_peer_wfd_device_info.data(), peer_wfd_device_info, kWfdDeviceInfoLen); } } callWithEachP2pIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onDeviceFound, std::placeholders::_1, addr, info->p2p_device_addr, info->pri_dev_type, info->device_name, info->config_methods, info->dev_capab, info->group_capab, hidl_peer_wfd_device_info)); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onDeviceLost, std::placeholders::_1, p2p_device_addr)); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onFindStopped, std::placeholders::_1)); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onGoNegotiationRequest, std::placeholders::_1, src_addr, static_cast<ISupplicantP2pIfaceCallback::WpsDevPasswordId>( dev_passwd_id))); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onGoNegotiationCompleted, std::placeholders::_1, static_cast<ISupplicantP2pIfaceCallback::P2pStatusCode>( res->status))); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onGroupFormationFailure, std::placeholders::_1, reason)); } void HidlManager::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 = wpa_group_s->parent; if (p2p_iface_object_map_.find(wpa_s->ifname) == p2p_iface_object_map_.end()) return; uint32_t hidl_freq = wpa_group_s->current_bss ? wpa_group_s->current_bss->freq : wpa_group_s->assoc_freq; std::array<uint8_t, 32> hidl_psk; if (ssid->psk_set) { os_memcpy(hidl_psk.data(), ssid->psk, 32); } bool hidl_is_go = (client == 0 ? true : false); bool hidl_is_persistent = (persistent == 1 ? true : false); callWithEachP2pIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onGroupStarted, std::placeholders::_1, wpa_group_s->ifname, hidl_is_go, std::vector<uint8_t>{ssid->ssid, ssid->ssid + ssid->ssid_len}, hidl_freq, hidl_psk, ssid->passphrase, wpa_group_s->go_dev_addr, hidl_is_persistent)); } void HidlManager::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 = wpa_group_s->parent; if (p2p_iface_object_map_.find(wpa_s->ifname) == p2p_iface_object_map_.end()) return; bool hidl_is_go = (std::string(role) == "GO"); callWithEachP2pIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onGroupRemoved, std::placeholders::_1, wpa_group_s->ifname, hidl_is_go)); } void HidlManager::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; SupplicantNetworkId hidl_network_id; if (id < 0) { hidl_network_id = UINT32_MAX; } hidl_network_id = id; callWithEachP2pIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onInvitationReceived, std::placeholders::_1, sa, go_dev_addr, bssid, hidl_network_id, op_freq)); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onInvitationResult, std::placeholders::_1, bssid ? bssid : kZeroBssid, static_cast<ISupplicantP2pIfaceCallback::P2pStatusCode>( status))); } void HidlManager::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 hidl_generated_pin; if (generated_pin > 0) { hidl_generated_pin = misc_utils::convertWpsPinToString(generated_pin); } bool hidl_is_request = (request == 1 ? true : false); callWithEachP2pIfaceCallback( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onProvisionDiscoveryCompleted, std::placeholders::_1, dev_addr, hidl_is_request, static_cast<ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode>( status), config_methods, hidl_generated_pin)); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantP2pIfaceCallback::onServiceDiscoveryResponse, std::placeholders::_1, sa, update_indic, std::vector<uint8_t>{tlvs, tlvs + tlvs_len})); } void HidlManager::notifyApStaAuthorized( struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr) { if (!wpa_s || !wpa_s->parent || !sta) return; if (p2p_iface_object_map_.find(wpa_s->parent->ifname) == p2p_iface_object_map_.end()) return; callWithEachP2pIfaceCallback( wpa_s->parent->ifname, std::bind( &ISupplicantP2pIfaceCallback::onStaAuthorized, std::placeholders::_1, sta, p2p_dev_addr ? p2p_dev_addr : kZeroBssid)); } void HidlManager::notifyApStaDeauthorized( struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr) { if (!wpa_s || !wpa_s->parent || !sta) return; if (p2p_iface_object_map_.find(wpa_s->parent->ifname) == p2p_iface_object_map_.end()) return; callWithEachP2pIfaceCallback( wpa_s->parent->ifname, std::bind( &ISupplicantP2pIfaceCallback::onStaDeauthorized, std::placeholders::_1, sta, p2p_dev_addr ? p2p_dev_addr : kZeroBssid)); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onExtRadioWorkStart, std::placeholders::_1, id)); } void HidlManager::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( wpa_s->ifname, std::bind( &ISupplicantStaIfaceCallback::onExtRadioWorkTimeout, std::placeholders::_1, id)); } void HidlManager::notifyEapError(struct wpa_supplicant *wpa_s, int error_code) { typedef V1_1::ISupplicantStaIfaceCallback::EapErrorCode EapErrorCode; if (!wpa_s) return; switch (static_cast<EapErrorCode>(error_code)) { case EapErrorCode::SIM_GENERAL_FAILURE_AFTER_AUTH: case EapErrorCode::SIM_TEMPORARILY_DENIED: case EapErrorCode::SIM_NOT_SUBSCRIBED: case EapErrorCode::SIM_GENERAL_FAILURE_BEFORE_AUTH: case EapErrorCode::SIM_VENDOR_SPECIFIC_EXPIRED_CERT: break; default: return; } callWithEachStaIfaceCallback_1_1( wpa_s->ifname, std::bind( &V1_1::ISupplicantStaIfaceCallback::onEapFailure_1_1, std::placeholders::_1, static_cast<EapErrorCode>(error_code))); } /** * Notify listener about a new DPP configuration received success event * * @param ifname Interface name * @param config Configuration object */ void HidlManager::notifyDppConfigReceived(struct wpa_supplicant *wpa_s, struct wpa_ssid *config) { DppAkm securityAkm; char *password; std::string hidl_ifname = 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; } password = config->passphrase; std::vector < uint8_t > hidl_ssid; hidl_ssid.assign(config->ssid, config->ssid + config->ssid_len); /* At this point, the network is already registered, notify about new * received configuration */ callWithEachStaIfaceCallback_1_2(hidl_ifname, std::bind( &V1_2::ISupplicantStaIfaceCallback::onDppSuccessConfigReceived, std::placeholders::_1, hidl_ssid, password, config->psk, securityAkm)); } /** * Notify listener about a DPP configuration sent success event * * @param ifname Interface name */ void HidlManager::notifyDppConfigSent(struct wpa_supplicant *wpa_s) { std::string hidl_ifname = wpa_s->ifname; callWithEachStaIfaceCallback_1_2(hidl_ifname, std::bind(&V1_2::ISupplicantStaIfaceCallback::onDppSuccessConfigSent, std::placeholders::_1)); } /** * Notify listener about a DPP failure event * * @param ifname Interface name * @param code Status code */ void HidlManager::notifyDppFailure(struct wpa_supplicant *wpa_s, DppFailureCode code) { std::string hidl_ifname = wpa_s->ifname; callWithEachStaIfaceCallback_1_2(hidl_ifname, std::bind(&V1_2::ISupplicantStaIfaceCallback::onDppFailure, std::placeholders::_1, code)); } /** * Notify listener about a DPP progress event * * @param ifname Interface name * @param code Status code */ void HidlManager::notifyDppProgress(struct wpa_supplicant *wpa_s, DppProgressCode code) { std::string hidl_ifname = wpa_s->ifname; callWithEachStaIfaceCallback_1_2(hidl_ifname, std::bind(&V1_2::ISupplicantStaIfaceCallback::onDppProgress, std::placeholders::_1, code)); } /** * Retrieve the |ISupplicantP2pIface| hidl object reference using the provided * ifname. * * @param ifname Name of the corresponding interface. * @param iface_object Hidl reference corresponding to the iface. * * @return 0 on success, 1 on failure. */ int HidlManager::getP2pIfaceHidlObjectByIfname( const std::string &ifname, android::sp<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| hidl object reference using the provided * ifname. * * @param ifname Name of the corresponding interface. * @param iface_object Hidl reference corresponding to the iface. * * @return 0 on success, 1 on failure. */ int HidlManager::getStaIfaceHidlObjectByIfname( const std::string &ifname, android::sp<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| hidl 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 Hidl reference corresponding to the network. * * @return 0 on success, 1 on failure. */ int HidlManager::getP2pNetworkHidlObjectByIfnameAndNetworkId( const std::string &ifname, int network_id, android::sp<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| hidl 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 Hidl reference corresponding to the network. * * @return 0 on success, 1 on failure. */ int HidlManager::getStaNetworkHidlObjectByIfnameAndNetworkId( const std::string &ifname, int network_id, android::sp<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| hidl object reference to our * global callback list. * * @param callback Hidl reference of the |ISupplicantCallback| object. * * @return 0 on success, 1 on failure. */ int HidlManager::addSupplicantCallbackHidlObject( const android::sp<ISupplicantCallback> &callback) { // Register for death notification before we add it to our list. auto on_hidl_died_fctor = std::bind( &HidlManager::removeSupplicantCallbackHidlObject, this, std::placeholders::_1); return registerForDeathAndAddCallbackHidlObjectToList< ISupplicantCallback>( callback, on_hidl_died_fctor, supplicant_callbacks_); } /** * Add a new iface callback hidl object reference to our * interface callback list. * * @param ifname Name of the corresponding interface. * @param callback Hidl reference of the callback object. * * @return 0 on success, 1 on failure. */ int HidlManager::addP2pIfaceCallbackHidlObject( const std::string &ifname, const android::sp<ISupplicantP2pIfaceCallback> &callback) { const std::function<void( const android::sp<ISupplicantP2pIfaceCallback> &)> on_hidl_died_fctor = std::bind( &HidlManager::removeP2pIfaceCallbackHidlObject, this, ifname, std::placeholders::_1); return addIfaceCallbackHidlObjectToMap( ifname, callback, on_hidl_died_fctor, p2p_iface_callbacks_map_); } /** * Add a new iface callback hidl object reference to our * interface callback list. * * @param ifname Name of the corresponding interface. * @param callback Hidl reference of the callback object. * * @return 0 on success, 1 on failure. */ int HidlManager::addStaIfaceCallbackHidlObject( const std::string &ifname, const android::sp<ISupplicantStaIfaceCallback> &callback) { const std::function<void( const android::sp<ISupplicantStaIfaceCallback> &)> on_hidl_died_fctor = std::bind( &HidlManager::removeStaIfaceCallbackHidlObject, this, ifname, std::placeholders::_1); return addIfaceCallbackHidlObjectToMap( ifname, callback, on_hidl_died_fctor, sta_iface_callbacks_map_); } /** * Add a new network callback hidl object reference to our network callback * list. * * @param ifname Name of the corresponding interface. * @param network_id ID of the corresponding network. * @param callback Hidl reference of the callback object. * * @return 0 on success, 1 on failure. */ int HidlManager::addP2pNetworkCallbackHidlObject( const std::string &ifname, int network_id, const android::sp<ISupplicantP2pNetworkCallback> &callback) { const std::function<void( const android::sp<ISupplicantP2pNetworkCallback> &)> on_hidl_died_fctor = std::bind( &HidlManager::removeP2pNetworkCallbackHidlObject, this, ifname, network_id, std::placeholders::_1); return addNetworkCallbackHidlObjectToMap( ifname, network_id, callback, on_hidl_died_fctor, p2p_network_callbacks_map_); } /** * Add a new network callback hidl object reference to our network callback * list. * * @param ifname Name of the corresponding interface. * @param network_id ID of the corresponding network. * @param callback Hidl reference of the callback object. * * @return 0 on success, 1 on failure. */ int HidlManager::addStaNetworkCallbackHidlObject( const std::string &ifname, int network_id, const android::sp<ISupplicantStaNetworkCallback> &callback) { const std::function<void( const android::sp<ISupplicantStaNetworkCallback> &)> on_hidl_died_fctor = std::bind( &HidlManager::removeStaNetworkCallbackHidlObject, this, ifname, network_id, std::placeholders::_1); return addNetworkCallbackHidlObjectToMap( ifname, network_id, callback, on_hidl_died_fctor, sta_network_callbacks_map_); } /** * Removes the provided |ISupplicantCallback| hidl object reference * from our global callback list. * * @param callback Hidl reference of the |ISupplicantCallback| object. */ void HidlManager::removeSupplicantCallbackHidlObject( const android::sp<ISupplicantCallback> &callback) { supplicant_callbacks_.erase( std::remove( supplicant_callbacks_.begin(), supplicant_callbacks_.end(), callback), supplicant_callbacks_.end()); } /** * Removes the provided iface callback hidl object reference from * our interface callback list. * * @param ifname Name of the corresponding interface. * @param callback Hidl reference of the callback object. */ void HidlManager::removeP2pIfaceCallbackHidlObject( const std::string &ifname, const android::sp<ISupplicantP2pIfaceCallback> &callback) { return removeIfaceCallbackHidlObjectFromMap( ifname, callback, p2p_iface_callbacks_map_); } /** * Removes the provided iface callback hidl object reference from * our interface callback list. * * @param ifname Name of the corresponding interface. * @param callback Hidl reference of the callback object. */ void HidlManager::removeStaIfaceCallbackHidlObject( const std::string &ifname, const android::sp<ISupplicantStaIfaceCallback> &callback) { return removeIfaceCallbackHidlObjectFromMap( ifname, callback, sta_iface_callbacks_map_); } /** * Removes the provided network callback hidl object reference from * our network callback list. * * @param ifname Name of the corresponding interface. * @param network_id ID of the corresponding network. * @param callback Hidl reference of the callback object. */ void HidlManager::removeP2pNetworkCallbackHidlObject( const std::string &ifname, int network_id, const android::sp<ISupplicantP2pNetworkCallback> &callback) { return removeNetworkCallbackHidlObjectFromMap( ifname, network_id, callback, p2p_network_callbacks_map_); } /** * Removes the provided network callback hidl object reference from * our network callback list. * * @param ifname Name of the corresponding interface. * @param network_id ID of the corresponding network. * @param callback Hidl reference of the callback object. */ void HidlManager::removeStaNetworkCallbackHidlObject( const std::string &ifname, int network_id, const android::sp<ISupplicantStaNetworkCallback> &callback) { return removeNetworkCallbackHidlObjectFromMap( ifname, network_id, callback, sta_network_callbacks_map_); } /** * Helper function to invoke the provided callback method on all the * registered |ISupplicantCallback| callback hidl objects. * * @param method Pointer to the required hidl method from * |ISupplicantCallback|. */ void HidlManager::callWithEachSupplicantCallback( const std::function<Return<void>(android::sp<ISupplicantCallback>)> &method) { for (const auto &callback : supplicant_callbacks_) { if (!method(callback).isOk()) { wpa_printf(MSG_ERROR, "Failed to invoke HIDL callback"); } } } /** * Helper fucntion to invoke the provided callback method on all the * registered iface callback hidl objects for the specified * |ifname|. * * @param ifname Name of the corresponding interface. * @param method Pointer to the required hidl method from * |ISupplicantIfaceCallback|. */ void HidlManager::callWithEachP2pIfaceCallback( const std::string &ifname, const std::function<Return<void>(android::sp<ISupplicantP2pIfaceCallback>)> &method) { callWithEachIfaceCallback(ifname, method, p2p_iface_callbacks_map_); } /** * Helper function to invoke the provided callback method on all the * registered V1.1 interface callback hidl objects for the specified * |ifname|. * * @param ifname Name of the corresponding interface. * @param method Pointer to the required hidl method from * |V1_1::ISupplicantIfaceCallback|. */ void HidlManager::callWithEachStaIfaceCallback_1_1( const std::string &ifname, const std::function< Return<void>(android::sp<V1_1::ISupplicantStaIfaceCallback>)> &method) { callWithEachIfaceCallback_1_1(ifname, method, sta_iface_callbacks_map_); } /** * Helper function to invoke the provided callback method on all the * registered V1.2 interface callback hidl objects for the specified * |ifname|. * * @param ifname Name of the corresponding interface. * @param method Pointer to the required hidl method from * |V1_2::ISupplicantIfaceCallback|. */ void HidlManager::callWithEachStaIfaceCallback_1_2( const std::string &ifname, const std::function< Return<void>(android::sp<V1_2::ISupplicantStaIfaceCallback>)> &method) { callWithEachIfaceCallback_1_2(ifname, method, sta_iface_callbacks_map_); } /** * Helper function to invoke the provided callback method on all the * registered interface callback hidl objects for the specified * |ifname|. * * @param ifname Name of the corresponding interface. * @param method Pointer to the required hidl method from * |ISupplicantIfaceCallback|. */ void HidlManager::callWithEachStaIfaceCallback( const std::string &ifname, const std::function<Return<void>(android::sp<ISupplicantStaIfaceCallback>)> &method) { callWithEachIfaceCallback(ifname, method, sta_iface_callbacks_map_); } /** * Helper function to invoke the provided callback method on all the * registered network callback hidl 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 hidl method from * |ISupplicantP2pNetworkCallback| or |ISupplicantStaNetworkCallback| . */ void HidlManager::callWithEachP2pNetworkCallback( const std::string &ifname, int network_id, const std::function< Return<void>(android::sp<ISupplicantP2pNetworkCallback>)> &method) { callWithEachNetworkCallback( ifname, network_id, method, p2p_network_callbacks_map_); } /** * Helper function to invoke the provided callback method on all the * registered network callback hidl 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 hidl method from * |ISupplicantP2pNetworkCallback| or |ISupplicantStaNetworkCallback| . */ void HidlManager::callWithEachStaNetworkCallback( const std::string &ifname, int network_id, const std::function< Return<void>(android::sp<ISupplicantStaNetworkCallback>)> &method) { callWithEachNetworkCallback( ifname, network_id, method, sta_network_callbacks_map_); } } // namespace implementation } // namespace V1_2 } // namespace supplicant } // namespace wifi } // namespace hardware } // namespace android