Merge "wpa_supplicant(hidl): Implementation of ext radio work" am: b462de3968 am: d613c43c01
am: f2ea8cfcb5

Change-Id: I2ad9ab796734dc7305a7c51c8955d852788ffdc1
diff --git a/wpa_supplicant/hidl/hidl_manager.cpp b/wpa_supplicant/hidl/hidl_manager.cpp
index 2112cc9..2490151 100644
--- a/wpa_supplicant/hidl/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/hidl_manager.cpp
@@ -326,8 +326,7 @@
 {
 	// Create the main hidl service object and register it.
 	supplicant_object_ = new Supplicant(global);
-	if (supplicant_object_->registerAsService() !=
-	    android::NO_ERROR) {
+	if (supplicant_object_->registerAsService() != android::NO_ERROR) {
 		return 1;
 	}
 	return 0;
@@ -838,6 +837,40 @@
 		std::placeholders::_1));
 }
 
+void HidlManager::notifyExtRadioWorkStart(
+    struct wpa_supplicant *wpa_s, uint32_t id)
+{
+	if (!wpa_s)
+		return;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(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;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onExtRadioWorkTimeout,
+		std::placeholders::_1, id));
+}
+
 /**
  * Retrieve the |ISupplicantP2pIface| hidl object reference using the provided
  * ifname.
diff --git a/wpa_supplicant/hidl/hidl_manager.h b/wpa_supplicant/hidl/hidl_manager.h
index 5d2ba8c..14fd726 100644
--- a/wpa_supplicant/hidl/hidl_manager.h
+++ b/wpa_supplicant/hidl/hidl_manager.h
@@ -83,6 +83,10 @@
 	void notifyWpsEventPbcOverlap(struct wpa_supplicant *wpa_s);
 
 	// Methods called from hidl objects.
+	void notifyExtRadioWorkStart(struct wpa_supplicant *wpa_s, uint32_t id);
+	void notifyExtRadioWorkTimeout(
+	    struct wpa_supplicant *wpa_s, uint32_t id);
+
 	int getP2pIfaceHidlObjectByIfname(
 	    const std::string &ifname,
 	    android::sp<ISupplicantP2pIface> *iface_object);
@@ -321,7 +325,8 @@
 	WPA_CIPHER_CCMP,
     "GroupCipher value mismatch");
 static_assert(
-    static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::GTK_NOT_USED) ==
+    static_cast<uint32_t>(
+	ISupplicantStaNetwork::GroupCipherMask::GTK_NOT_USED) ==
 	WPA_CIPHER_GTK_NOT_USED,
     "GroupCipher value mismatch");
 static_assert(
diff --git a/wpa_supplicant/hidl/iface_config_utils.cpp b/wpa_supplicant/hidl/iface_config_utils.cpp
index 86ed4c1..028eae8 100644
--- a/wpa_supplicant/hidl/iface_config_utils.cpp
+++ b/wpa_supplicant/hidl/iface_config_utils.cpp
@@ -20,10 +20,16 @@
 constexpr uint32_t kMaxWpsModelNumberSize = 32;
 constexpr uint32_t kMaxWpsSerialNumberSize = 32;
 
+void processConfigUpdate(struct wpa_supplicant* wpa_s, uint32_t changed_param)
+{
+	wpa_s->conf->changed_parameters |= changed_param;
+	wpa_supplicant_update_config(wpa_s);
+}
+
 // Free any existing pointer stored in |dst| and store the provided string value
 // there.
 int freeAndSetStringConfigParam(
-    wpa_supplicant* wpa_s, const std::string& value, uint32_t max_size,
+    struct wpa_supplicant* wpa_s, const std::string& value, uint32_t max_size,
     uint32_t changed_param, char** dst)
 {
 	if (value.size() > max_size) {
@@ -32,8 +38,7 @@
 	WPA_ASSERT(dst);
 	os_free(static_cast<void*>(*dst));
 	*dst = os_strdup(value.c_str());
-	wpa_s->conf->changed_parameters |= changed_param;
-	wpa_supplicant_update_config(wpa_s);
+	processConfigUpdate(wpa_s, changed_param);
 	return 0;
 }
 
@@ -85,6 +90,16 @@
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
+SupplicantStatus setWpsDeviceType(
+    struct wpa_supplicant* wpa_s, const std::array<uint8_t, 8>& type)
+{
+	WPA_ASSERT(wpa_s);
+	WPA_ASSERT(type.size() == WPS_DEV_TYPE_LEN);
+	os_memcpy(wpa_s->conf->device_type, type.data(), WPS_DEV_TYPE_LEN);
+	processConfigUpdate(wpa_s, CFG_CHANGED_DEVICE_TYPE);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
 SupplicantStatus setWpsManufacturer(
     struct wpa_supplicant* wpa_s, const std::string& manufacturer)
 {
diff --git a/wpa_supplicant/hidl/iface_config_utils.h b/wpa_supplicant/hidl/iface_config_utils.h
index fb72bbc..789cc38 100644
--- a/wpa_supplicant/hidl/iface_config_utils.h
+++ b/wpa_supplicant/hidl/iface_config_utils.h
@@ -34,6 +34,8 @@
 namespace iface_config_utils {
 SupplicantStatus setWpsDeviceName(
     struct wpa_supplicant* wpa_s, const std::string& name);
+SupplicantStatus setWpsDeviceType(
+    struct wpa_supplicant* wpa_s, const std::array<uint8_t, 8>& type);
 SupplicantStatus setWpsManufacturer(
     struct wpa_supplicant* wpa_s, const std::string& manufacturer);
 SupplicantStatus setWpsModelName(
diff --git a/wpa_supplicant/hidl/p2p_iface.cpp b/wpa_supplicant/hidl/p2p_iface.cpp
index 2bcfdfd..706ac1a 100644
--- a/wpa_supplicant/hidl/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/p2p_iface.cpp
@@ -399,6 +399,14 @@
 	    &P2pIface::setWpsDeviceNameInternal, _hidl_cb, name);
 }
 
+Return<void> P2pIface::setWpsDeviceType(
+    const hidl_array<uint8_t, 8>& type, setWpsDeviceType_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setWpsDeviceTypeInternal, _hidl_cb, type);
+}
+
 Return<void> P2pIface::setWpsManufacturer(
     const hidl_string& manufacturer, setWpsManufacturer_cb _hidl_cb)
 {
@@ -1052,6 +1060,12 @@
 	return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
 }
 
+SupplicantStatus P2pIface::setWpsDeviceTypeInternal(
+    const std::array<uint8_t, 8>& type)
+{
+	return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type);
+}
+
 SupplicantStatus P2pIface::setWpsManufacturerInternal(
     const std::string& manufacturer)
 {
diff --git a/wpa_supplicant/hidl/p2p_iface.h b/wpa_supplicant/hidl/p2p_iface.h
index a0b3aef..07551bd 100644
--- a/wpa_supplicant/hidl/p2p_iface.h
+++ b/wpa_supplicant/hidl/p2p_iface.h
@@ -153,6 +153,9 @@
 	    const hidl_string& groupIfName, cancelWps_cb _hidl_cb) override;
 	Return<void> setWpsDeviceName(
 	    const hidl_string& name, setWpsDeviceName_cb _hidl_cb) override;
+	Return<void> setWpsDeviceType(
+	    const hidl_array<uint8_t, 8>& type,
+	    setWpsDeviceType_cb _hidl_cb) override;
 	Return<void> setWpsManufacturer(
 	    const hidl_string& manufacturer,
 	    setWpsManufacturer_cb _hidl_cb) override;
@@ -253,6 +256,8 @@
 	    const std::array<uint8_t, 6>& bssid);
 	SupplicantStatus cancelWpsInternal(const std::string& group_ifname);
 	SupplicantStatus setWpsDeviceNameInternal(const std::string& name);
+	SupplicantStatus setWpsDeviceTypeInternal(
+	    const std::array<uint8_t, 8>& type);
 	SupplicantStatus setWpsManufacturerInternal(
 	    const std::string& manufacturer);
 	SupplicantStatus setWpsModelNameInternal(const std::string& model_name);
diff --git a/wpa_supplicant/hidl/sta_iface.cpp b/wpa_supplicant/hidl/sta_iface.cpp
index b7c6ac9..8ce80bb 100644
--- a/wpa_supplicant/hidl/sta_iface.cpp
+++ b/wpa_supplicant/hidl/sta_iface.cpp
@@ -13,6 +13,7 @@
 #include "sta_iface.h"
 
 extern "C" {
+#include "utils/eloop.h"
 #include "gas_query.h"
 #include "interworking.h"
 #include "hs20_supplicant.h"
@@ -20,6 +21,11 @@
 }
 
 namespace {
+using android::hardware::wifi::supplicant::V1_0::ISupplicantStaIface;
+using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+using android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+using android::hardware::wifi::supplicant::V1_0::implementation::HidlManager;
+
 constexpr uint32_t kMaxAnqpElems = 100;
 constexpr char kGetMacAddress[] = "MACADDR";
 constexpr char kStartRxFilter[] = "RXFILTER-START";
@@ -32,10 +38,9 @@
 constexpr char kSetSupendModeEnabled[] = "SETSUSPENDMODE 1";
 constexpr char kSetSupendModeDisabled[] = "SETSUSPENDMODE 0";
 constexpr char kSetCountryCode[] = "COUNTRY ";
-
-using android::hardware::wifi::supplicant::V1_0::ISupplicantStaIface;
-using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
-using android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+constexpr uint32_t kExtRadioWorkDefaultTimeoutInSec = static_cast<uint32_t>(
+    ISupplicantStaIface::ExtRadioWorkDefaults::TIMEOUT_IN_SECS);
+constexpr char kExtRadioWorkNamePrefix[] = "ext:";
 
 uint8_t convertHidlRxFilterTypeToInternal(
     ISupplicantStaIface::RxFilterType type)
@@ -89,6 +94,60 @@
 	std::string cmd_str = std::string(cmd) + " " + arg;
 	return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
 }
+
+void endExtRadioWork(struct wpa_radio_work *work)
+{
+	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+	work->wpa_s->ext_work_in_progress = 0;
+	radio_work_done(work);
+	os_free(ework);
+}
+
+void extRadioWorkTimeoutCb(void *eloop_ctx, void *timeout_ctx)
+{
+	auto *work = static_cast<struct wpa_radio_work *>(eloop_ctx);
+	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+	wpa_dbg(
+	    work->wpa_s, MSG_DEBUG, "Timing out external radio work %u (%s)",
+	    ework->id, work->type);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	WPA_ASSERT(hidl_manager);
+	hidl_manager->notifyExtRadioWorkTimeout(work->wpa_s, ework->id);
+
+	endExtRadioWork(work);
+}
+
+void startExtRadioWork(struct wpa_radio_work *work)
+{
+	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+	work->wpa_s->ext_work_in_progress = 1;
+	if (!ework->timeout) {
+		ework->timeout = kExtRadioWorkDefaultTimeoutInSec;
+	}
+	eloop_register_timeout(
+	    ework->timeout, 0, extRadioWorkTimeoutCb, work, nullptr);
+}
+
+void extRadioWorkStartCb(struct wpa_radio_work *work, int deinit)
+{
+	// deinit==1 is invoked during interface removal. Since the HIDL
+	// interface does not support interface addition/removal, we don't
+	// need to handle this scenario.
+	WPA_ASSERT(!deinit);
+
+	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+	wpa_dbg(
+	    work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
+	    ework->id, ework->type);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	WPA_ASSERT(hidl_manager);
+	hidl_manager->notifyExtRadioWorkStart(work->wpa_s, ework->id);
+
+	startExtRadioWork(work);
+}
+
 }  // namespace
 
 namespace android {
@@ -355,6 +414,14 @@
 	    &StaIface::setWpsDeviceNameInternal, _hidl_cb, name);
 }
 
+Return<void> StaIface::setWpsDeviceType(
+    const hidl_array<uint8_t, 8> &type, setWpsDeviceType_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setWpsDeviceTypeInternal, _hidl_cb, type);
+}
+
 Return<void> StaIface::setWpsManufacturer(
     const hidl_string &manufacturer, setWpsManufacturer_cb _hidl_cb)
 {
@@ -403,6 +470,24 @@
 	    &StaIface::setExternalSimInternal, _hidl_cb, useExternalSim);
 }
 
+Return<void> StaIface::addExtRadioWork(
+    const hidl_string &name, uint32_t freq_in_mhz, uint32_t timeout_in_sec,
+    addExtRadioWork_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::addExtRadioWorkInternal, _hidl_cb, name, freq_in_mhz,
+	    timeout_in_sec);
+}
+
+Return<void> StaIface::removeExtRadioWork(
+    uint32_t id, removeExtRadioWork_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::removeExtRadioWorkInternal, _hidl_cb, id);
+}
+
 std::pair<SupplicantStatus, std::string> StaIface::getNameInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
@@ -800,6 +885,12 @@
 	return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
 }
 
+SupplicantStatus StaIface::setWpsDeviceTypeInternal(
+    const std::array<uint8_t, 8> &type)
+{
+	return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type);
+}
+
 SupplicantStatus StaIface::setWpsManufacturerInternal(
     const std::string &manufacturer)
 {
@@ -840,6 +931,63 @@
 	    retrieveIfacePtr(), useExternalSim);
 }
 
+std::pair<SupplicantStatus, uint32_t> StaIface::addExtRadioWorkInternal(
+    const std::string &name, uint32_t freq_in_mhz, uint32_t timeout_in_sec)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	auto *ework = static_cast<struct wpa_external_work *>(
+	    os_zalloc(sizeof(struct wpa_external_work)));
+	if (!ework) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
+			UINT32_MAX};
+	}
+
+	std::string radio_work_name = kExtRadioWorkNamePrefix + name;
+	os_strlcpy(ework->type, radio_work_name.c_str(), sizeof(ework->type));
+	ework->timeout = timeout_in_sec;
+	wpa_s->ext_work_id++;
+	if (wpa_s->ext_work_id == 0) {
+		wpa_s->ext_work_id++;
+	}
+	ework->id = wpa_s->ext_work_id;
+
+	if (radio_add_work(
+		wpa_s, freq_in_mhz, ework->type, 0, extRadioWorkStartCb,
+		ework)) {
+		os_free(ework);
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
+			UINT32_MAX};
+	}
+	return {SupplicantStatus{SupplicantStatusCode::SUCCESS, ""}, ework->id};
+}
+
+SupplicantStatus StaIface::removeExtRadioWorkInternal(uint32_t id)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_radio_work *work;
+	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
+	{
+		if (os_strncmp(
+			work->type, kExtRadioWorkNamePrefix,
+			sizeof(kExtRadioWorkNamePrefix)) != 0)
+			continue;
+
+		auto *ework =
+		    static_cast<struct wpa_external_work *>(work->ctx);
+		if (ework->id != id)
+			continue;
+
+		wpa_dbg(
+		    wpa_s, MSG_DEBUG, "Completed external radio work %u (%s)",
+		    ework->id, ework->type);
+		eloop_cancel_timeout(extRadioWorkTimeoutCb, work, NULL);
+		endExtRadioWork(work);
+
+		return {SupplicantStatusCode::SUCCESS, ""};
+	}
+	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+}
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/hidl/sta_iface.h b/wpa_supplicant/hidl/sta_iface.h
index cf90d07..32e0e7c 100644
--- a/wpa_supplicant/hidl/sta_iface.h
+++ b/wpa_supplicant/hidl/sta_iface.h
@@ -129,6 +129,9 @@
 	Return<void> cancelWps(cancelWps_cb _hidl_cb) override;
 	Return<void> setWpsDeviceName(
 	    const hidl_string& name, setWpsDeviceName_cb _hidl_cb) override;
+	Return<void> setWpsDeviceType(
+	    const hidl_array<uint8_t, 8>& type,
+	    setWpsDeviceType_cb _hidl_cb) override;
 	Return<void> setWpsManufacturer(
 	    const hidl_string& manufacturer,
 	    setWpsManufacturer_cb _hidl_cb) override;
@@ -145,6 +148,11 @@
 	    uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb) override;
 	Return<void> setExternalSim(
 	    bool useExternalSim, setExternalSim_cb _hidl_cb) override;
+	Return<void> addExtRadioWork(
+	    const hidl_string& name, uint32_t freq_in_mhz,
+	    uint32_t timeout_in_sec, addExtRadioWork_cb _hidl_cb) override;
+	Return<void> removeExtRadioWork(
+	    uint32_t id, removeExtRadioWork_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -200,6 +208,8 @@
 	    const std::array<uint8_t, 6>& bssid);
 	SupplicantStatus cancelWpsInternal();
 	SupplicantStatus setWpsDeviceNameInternal(const std::string& name);
+	SupplicantStatus setWpsDeviceTypeInternal(
+	    const std::array<uint8_t, 8>& type);
 	SupplicantStatus setWpsManufacturerInternal(
 	    const std::string& manufacturer);
 	SupplicantStatus setWpsModelNameInternal(const std::string& model_name);
@@ -209,6 +219,10 @@
 	    const std::string& serial_number);
 	SupplicantStatus setWpsConfigMethodsInternal(uint16_t config_methods);
 	SupplicantStatus setExternalSimInternal(bool useExternalSim);
+	std::pair<SupplicantStatus, uint32_t> addExtRadioWorkInternal(
+	    const std::string& name, uint32_t freq_in_mhz,
+	    uint32_t timeout_in_sec);
+	SupplicantStatus removeExtRadioWorkInternal(uint32_t id);
 
 	struct wpa_supplicant* retrieveIfacePtr();
 
diff --git a/wpa_supplicant/hidl/sta_network.cpp b/wpa_supplicant/hidl/sta_network.cpp
index 8ae5cbd..cae61e6 100644
--- a/wpa_supplicant/hidl/sta_network.cpp
+++ b/wpa_supplicant/hidl/sta_network.cpp
@@ -38,7 +38,8 @@
      static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::WEP104) |
      static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::TKIP) |
      static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::CCMP) |
-     static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::GTK_NOT_USED));
+     static_cast<uint32_t>(
+	 ISupplicantStaNetwork::GroupCipherMask::GTK_NOT_USED));
 constexpr uint32_t kAllowedpairwise_cipher_mask =
     (static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::NONE) |
      static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::TKIP) |
@@ -54,6 +55,11 @@
     "NULL", "PAP", "MSCHAP", "MSCHAPV2", "GTC"};
 constexpr char kEapPhase2AuthPrefix[] = "auth=";
 constexpr char kEapPhase2AuthEapPrefix[] = "autheap=";
+constexpr char kNetworkEapSimGsmAuthResponse[] = "GSM-AUTH";
+constexpr char kNetworkEapSimUmtsAuthResponse[] = "UMTS-AUTH";
+constexpr char kNetworkEapSimUmtsAutsResponse[] = "UMTS-AUTS";
+constexpr char kNetworkEapSimGsmAuthFailure[] = "GSM-FAIL";
+constexpr char kNetworkEapSimUmtsAuthFailure[] = "UMTS-FAIL";
 }  // namespace
 
 namespace android {
@@ -316,6 +322,14 @@
 	    &StaNetwork::setEapDomainSuffixMatchInternal, _hidl_cb, match);
 }
 
+Return<void> StaNetwork::setProactiveKeyCaching(
+    bool enable, setProactiveKeyCaching_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setProactiveKeyCachingInternal, _hidl_cb, enable);
+}
+
 Return<void> StaNetwork::setIdStr(
     const hidl_string &id_str, setIdStr_cb _hidl_cb)
 {
@@ -324,6 +338,14 @@
 	    &StaNetwork::setIdStrInternal, _hidl_cb, id_str);
 }
 
+Return<void> StaNetwork::setUpdateIdentifier(
+    uint32_t id, setUpdateIdentifier_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setUpdateIdentifierInternal, _hidl_cb, id);
+}
+
 Return<void> StaNetwork::getSsid(getSsid_cb _hidl_cb)
 {
 	return validateAndCall(
@@ -538,13 +560,22 @@
 }
 
 Return<void> StaNetwork::sendNetworkEapSimGsmAuthResponse(
-    const ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams &params,
+    const hidl_vec<ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>
+	&vec_params,
     sendNetworkEapSimGsmAuthResponse_cb _hidl_cb)
 {
 	return validateAndCall(
 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
 	    &StaNetwork::sendNetworkEapSimGsmAuthResponseInternal, _hidl_cb,
-	    params);
+	    vec_params);
+}
+
+Return<void> StaNetwork::sendNetworkEapSimGsmAuthFailure(
+    sendNetworkEapSimGsmAuthFailure_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::sendNetworkEapSimGsmAuthFailureInternal, _hidl_cb);
 }
 
 Return<void> StaNetwork::sendNetworkEapSimUmtsAuthResponse(
@@ -557,6 +588,24 @@
 	    params);
 }
 
+Return<void> StaNetwork::sendNetworkEapSimUmtsAutsResponse(
+    const hidl_array<uint8_t, 14> &auts,
+    sendNetworkEapSimUmtsAutsResponse_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::sendNetworkEapSimUmtsAutsResponseInternal, _hidl_cb,
+	    auts);
+}
+
+Return<void> StaNetwork::sendNetworkEapSimUmtsAuthFailure(
+    sendNetworkEapSimUmtsAuthFailure_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::sendNetworkEapSimUmtsAuthFailureInternal, _hidl_cb);
+}
+
 Return<void> StaNetwork::sendNetworkEapIdentityResponse(
     const hidl_vec<uint8_t> &identity,
     sendNetworkEapIdentityResponse_cb _hidl_cb)
@@ -1005,6 +1054,14 @@
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
+SupplicantStatus StaNetwork::setProactiveKeyCachingInternal(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->proactive_key_caching = enable ? 1 : 0;
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
 SupplicantStatus StaNetwork::setIdStrInternal(const std::string &id_str)
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
@@ -1015,6 +1072,16 @@
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
+SupplicantStatus StaNetwork::setUpdateIdentifierInternal(uint32_t id)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->update_identifier = id;
+	wpa_printf(
+	    MSG_MSGDUMP, "update_identifier: %d", wpa_ssid->update_identifier);
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
 std::pair<SupplicantStatus, std::vector<uint8_t>> StaNetwork::getSsidInternal()
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
@@ -1354,22 +1421,27 @@
 }
 
 SupplicantStatus StaNetwork::sendNetworkEapSimGsmAuthResponseInternal(
-    const ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams &params)
+    const std::vector<ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>
+	&vec_params)
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
 	// Convert the incoming parameters to a string to pass to
 	// wpa_supplicant.
-	uint32_t kc_hex_len = params.kc.size() * 2 + 1;
-	std::vector<char> kc_hex(kc_hex_len);
-	uint32_t sres_hex_len = params.sres.size() * 2 + 1;
-	std::vector<char> sres_hex(sres_hex_len);
-	wpa_snprintf_hex(
-	    kc_hex.data(), kc_hex.size(), params.kc.data(), params.kc.size());
-	wpa_snprintf_hex(
-	    sres_hex.data(), sres_hex.size(), params.sres.data(),
-	    params.sres.size());
-	std::string ctrl_rsp_param = ":" + std::string(kc_hex.data()) + ":" +
-				     std::string(sres_hex.data());
+	std::string ctrl_rsp_param = std::string(kNetworkEapSimGsmAuthResponse);
+	for (const auto &params : vec_params) {
+		uint32_t kc_hex_len = params.kc.size() * 2 + 1;
+		std::vector<char> kc_hex(kc_hex_len);
+		uint32_t sres_hex_len = params.sres.size() * 2 + 1;
+		std::vector<char> sres_hex(sres_hex_len);
+		wpa_snprintf_hex(
+		    kc_hex.data(), kc_hex.size(), params.kc.data(),
+		    params.kc.size());
+		wpa_snprintf_hex(
+		    sres_hex.data(), sres_hex.size(), params.sres.data(),
+		    params.sres.size());
+		ctrl_rsp_param += ":" + std::string(kc_hex.data()) + ":" +
+				  std::string(sres_hex.data());
+	}
 	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	if (wpa_supplicant_ctrl_rsp_handle(
@@ -1383,6 +1455,19 @@
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
+SupplicantStatus StaNetwork::sendNetworkEapSimGsmAuthFailureInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, kNetworkEapSimGsmAuthFailure)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
 SupplicantStatus StaNetwork::sendNetworkEapSimUmtsAuthResponseInternal(
     const ISupplicantStaNetwork::NetworkResponseEapSimUmtsAuthParams &params)
 {
@@ -1402,9 +1487,10 @@
 	wpa_snprintf_hex(
 	    res_hex.data(), res_hex.size(), params.res.data(),
 	    params.res.size());
-	std::string ctrl_rsp_param = ":" + std::string(ik_hex.data()) + ":" +
-				     std::string(ck_hex.data()) + ":" +
-				     std::string(res_hex.data());
+	std::string ctrl_rsp_param =
+	    std::string(kNetworkEapSimUmtsAuthResponse) + ":" +
+	    std::string(ik_hex.data()) + ":" + std::string(ck_hex.data()) +
+	    ":" + std::string(res_hex.data());
 	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	if (wpa_supplicant_ctrl_rsp_handle(
@@ -1418,6 +1504,43 @@
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
+SupplicantStatus StaNetwork::sendNetworkEapSimUmtsAutsResponseInternal(
+    const std::array<uint8_t, 14> &auts)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	uint32_t auts_hex_len = auts.size() * 2 + 1;
+	std::vector<char> auts_hex(auts_hex_len);
+	wpa_snprintf_hex(
+	    auts_hex.data(), auts_hex.size(), auts.data(), auts.size());
+	std::string ctrl_rsp_param =
+	    std::string(kNetworkEapSimUmtsAutsResponse) + ":" +
+	    std::string(auts_hex.data());
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	wpa_hexdump_ascii_key(
+	    MSG_DEBUG, "network sim umts auts response param",
+	    (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::sendNetworkEapSimUmtsAuthFailureInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, kNetworkEapSimUmtsAuthFailure)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
 SupplicantStatus StaNetwork::sendNetworkEapIdentityResponseInternal(
     const std::vector<uint8_t> &identity)
 {
diff --git a/wpa_supplicant/hidl/sta_network.h b/wpa_supplicant/hidl/sta_network.h
index 9c54e1d..063fa61 100644
--- a/wpa_supplicant/hidl/sta_network.h
+++ b/wpa_supplicant/hidl/sta_network.h
@@ -118,8 +118,12 @@
 	Return<void> setEapDomainSuffixMatch(
 	    const hidl_string& match,
 	    setEapDomainSuffixMatch_cb _hidl_cb) override;
+	Return<void> setProactiveKeyCaching(
+	    bool enable, setProactiveKeyCaching_cb _hidl_cb) override;
 	Return<void> setIdStr(
 	    const hidl_string& id_str, setIdStr_cb _hidl_cb) override;
+	Return<void> setUpdateIdentifier(
+	    uint32_t id, setUpdateIdentifier_cb _hidl_cb) override;
 	Return<void> getSsid(getSsid_cb _hidl_cb) override;
 	Return<void> getBssid(getBssid_cb _hidl_cb) override;
 	Return<void> getScanSsid(getScanSsid_cb _hidl_cb) override;
@@ -157,13 +161,21 @@
 	Return<void> disable(disable_cb _hidl_cb) override;
 	Return<void> select(select_cb _hidl_cb) override;
 	Return<void> sendNetworkEapSimGsmAuthResponse(
-	    const ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams&
-		params,
+	    const hidl_vec<
+		ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>&
+		vec_params,
 	    sendNetworkEapSimGsmAuthResponse_cb _hidl_cb) override;
+	Return<void> sendNetworkEapSimGsmAuthFailure(
+	    sendNetworkEapSimGsmAuthFailure_cb _hidl_cb) override;
 	Return<void> sendNetworkEapSimUmtsAuthResponse(
 	    const ISupplicantStaNetwork::NetworkResponseEapSimUmtsAuthParams&
 		params,
 	    sendNetworkEapSimUmtsAuthResponse_cb _hidl_cb) override;
+	Return<void> sendNetworkEapSimUmtsAutsResponse(
+	    const hidl_array<uint8_t, 14>& auts,
+	    sendNetworkEapSimUmtsAutsResponse_cb _hidl_cb) override;
+	Return<void> sendNetworkEapSimUmtsAuthFailure(
+	    sendNetworkEapSimUmtsAuthFailure_cb _hidl_cb) override;
 	Return<void> sendNetworkEapIdentityResponse(
 	    const hidl_vec<uint8_t>& identity,
 	    sendNetworkEapIdentityResponse_cb _hidl_cb) override;
@@ -210,7 +222,9 @@
 	SupplicantStatus setEapEngineIDInternal(const std::string& id);
 	SupplicantStatus setEapDomainSuffixMatchInternal(
 	    const std::string& match);
+	SupplicantStatus setProactiveKeyCachingInternal(bool enable);
 	SupplicantStatus setIdStrInternal(const std::string& id_str);
+	SupplicantStatus setUpdateIdentifierInternal(uint32_t id);
 	std::pair<SupplicantStatus, std::vector<uint8_t>> getSsidInternal();
 	std::pair<SupplicantStatus, std::array<uint8_t, 6>> getBssidInternal();
 	std::pair<SupplicantStatus, bool> getScanSsidInternal();
@@ -250,11 +264,16 @@
 	SupplicantStatus disableInternal();
 	SupplicantStatus selectInternal();
 	SupplicantStatus sendNetworkEapSimGsmAuthResponseInternal(
-	    const ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams&
-		params);
+	    const std::vector<
+		ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>&
+		vec_params);
+	SupplicantStatus sendNetworkEapSimGsmAuthFailureInternal();
 	SupplicantStatus sendNetworkEapSimUmtsAuthResponseInternal(
 	    const ISupplicantStaNetwork::NetworkResponseEapSimUmtsAuthParams&
 		params);
+	SupplicantStatus sendNetworkEapSimUmtsAutsResponseInternal(
+	    const std::array<uint8_t, 14>& auts);
+	SupplicantStatus sendNetworkEapSimUmtsAuthFailureInternal();
 	SupplicantStatus sendNetworkEapIdentityResponseInternal(
 	    const std::vector<uint8_t>& identity);