binder: Implement network addition/removal
Implement the |IIface.AddNetwork| & |IIface.RemoveNetwork| binder calls.
Also hookup the network addition notifications to BinderManager for
creating corresponding network binder objects. The network binder
objects are keyed using |ifname|_|network_id|.
BUG: 30015382
Change-Id: I0842563e74ff8b120d34f63fa28965bf264bb55f
TEST: Ran the integration tests under |wificond|.
Signed-off-by: Roshan Pius <rpius@google.com>
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 5ca994e..1363d84 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -1673,8 +1673,11 @@
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_C_INCLUDES := $(INCLUDES)
LOCAL_SRC_FILES := \
- binder/binder.cpp binder/binder_manager.cpp \
- binder/supplicant.cpp binder/iface.cpp
+ binder/binder.cpp \
+ binder/binder_manager.cpp \
+ binder/iface.cpp \
+ binder/network.cpp \
+ binder/supplicant.cpp
LOCAL_SHARED_LIBRARIES := \
libbinder \
libutils
diff --git a/wpa_supplicant/binder/binder.cpp b/wpa_supplicant/binder/binder.cpp
index 9fee001..704b1c3 100644
--- a/wpa_supplicant/binder/binder.cpp
+++ b/wpa_supplicant/binder/binder.cpp
@@ -116,3 +116,38 @@
return binder_manager->unregisterInterface(wpa_s);
}
+
+int wpas_binder_register_network(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+ if (!wpa_s->global->binder || !wpa_s || !ssid)
+ return 1;
+
+ wpa_printf(
+ MSG_DEBUG, "Registering network to binder control: %d", ssid->id);
+
+ wpa_supplicant_binder::BinderManager *binder_manager =
+ wpa_supplicant_binder::BinderManager::getInstance();
+ if (!binder_manager)
+ return 1;
+
+ return binder_manager->registerNetwork(wpa_s, ssid);
+}
+
+int wpas_binder_unregister_network(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+ if (!wpa_s->global->binder || !wpa_s || !ssid)
+ return 1;
+
+ wpa_printf(
+ MSG_DEBUG, "Deregistering network from binder control: %d",
+ ssid->id);
+
+ wpa_supplicant_binder::BinderManager *binder_manager =
+ wpa_supplicant_binder::BinderManager::getInstance();
+ if (!binder_manager)
+ return 1;
+
+ return binder_manager->unregisterNetwork(wpa_s, ssid);
+}
diff --git a/wpa_supplicant/binder/binder.h b/wpa_supplicant/binder/binder.h
index 019e327..4ca2c86 100644
--- a/wpa_supplicant/binder/binder.h
+++ b/wpa_supplicant/binder/binder.h
@@ -28,6 +28,10 @@
#ifdef CONFIG_CTRL_IFACE_BINDER
int wpas_binder_register_interface(struct wpa_supplicant *wpa_s);
int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s);
+int wpas_binder_register_network(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+int wpas_binder_unregister_network(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
#else /* CONFIG_CTRL_IFACE_BINDER */
static inline int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
{
@@ -37,6 +41,16 @@
{
return 0;
}
+static inline int wpas_binder_register_network(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+ return 0;
+}
+static inline int wpas_binder_unregister_network(
+ struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+ return 0;
+}
#endif /* CONFIG_CTRL_IFACE_BINDER */
#ifdef _cplusplus
diff --git a/wpa_supplicant/binder/binder_manager.cpp b/wpa_supplicant/binder/binder_manager.cpp
index 00fa70f..5152ed9 100644
--- a/wpa_supplicant/binder/binder_manager.cpp
+++ b/wpa_supplicant/binder/binder_manager.cpp
@@ -94,6 +94,63 @@
}
/**
+ * Register a network to binder 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 BinderManager::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 (network_object_map_.find(network_key) != network_object_map_.end())
+ return 1;
+
+ network_object_map_[network_key] =
+ new Network(wpa_s->global, wpa_s->ifname, ssid->id);
+ if (!network_object_map_[network_key].get())
+ return 1;
+
+ return 0;
+}
+
+/**
+ * Unregister a network from binder 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 BinderManager::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 (network_object_map_.find(network_key) == network_object_map_.end())
+ return 1;
+
+ /* Delete the corresponding network object from our map. */
+ network_object_map_.erase(network_key);
+ return 0;
+}
+
+/**
* Retrieve the |IIface| binder object reference using the provided ifname.
*
* @param ifname Name of the corresponding interface.
@@ -115,4 +172,46 @@
return 0;
}
+/**
+ * Retrieve the |INetwork| binder 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 Binder reference corresponding to the network.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int BinderManager::getNetworkBinderObjectByIfnameAndNetworkId(
+ const std::string &ifname, int network_id,
+ android::sp<fi::w1::wpa_supplicant::INetwork> *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);
+
+ if (network_object_map_.find(network_key) == network_object_map_.end())
+ return 1;
+
+ *network_object = network_object_map_[network_key];
+ return 0;
+}
+
+/**
+ * Creates a unique key for the network using the provided |ifname| and
+ * |network_id| to be used
+ * in the internal map of |INetwork| 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
+BinderManager::getNetworkObjectMapKey(const std::string &ifname, int network_id)
+{
+ return ifname + "_" + std::to_string(network_id);
+}
} // namespace wpa_supplicant_binder
diff --git a/wpa_supplicant/binder/binder_manager.h b/wpa_supplicant/binder/binder_manager.h
index b4b8f76..377c94f 100644
--- a/wpa_supplicant/binder/binder_manager.h
+++ b/wpa_supplicant/binder/binder_manager.h
@@ -14,6 +14,7 @@
#include <string>
#include "iface.h"
+#include "network.h"
#include "supplicant.h"
struct wpa_global;
@@ -32,12 +33,20 @@
public:
static BinderManager *getInstance();
static void destroyInstance();
+
int registerBinderService(struct wpa_global *global);
int registerInterface(struct wpa_supplicant *wpa_s);
int unregisterInterface(struct wpa_supplicant *wpa_s);
+ int
+ registerNetwork(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+ int
+ unregisterNetwork(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
int getIfaceBinderObjectByIfname(
const std::string &ifname,
android::sp<fi::w1::wpa_supplicant::IIface> *iface_object);
+ int getNetworkBinderObjectByIfnameAndNetworkId(
+ const std::string &ifname, int network_id,
+ android::sp<fi::w1::wpa_supplicant::INetwork> *network_object);
private:
BinderManager() = default;
@@ -45,6 +54,9 @@
BinderManager(const BinderManager &) = default;
BinderManager &operator=(const BinderManager &) = default;
+ const std::string
+ getNetworkObjectMapKey(const std::string &ifname, int network_id);
+
// Singleton instance of this class.
static BinderManager *instance_;
// The main binder service object.
@@ -53,6 +65,10 @@
// wpa_supplicant. This map is keyed in by the corresponding
// |ifname|.
std::map<const std::string, android::sp<Iface>> iface_object_map_;
+ // Map of all the network specific binder objects controlled by
+ // wpa_supplicant. This map is keyed in by the corresponding
+ // |ifname| & |network_id|.
+ std::map<const std::string, android::sp<Network>> network_object_map_;
};
} // namespace wpa_supplicant_binder
diff --git a/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl b/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl
index dd0fbaa..4e486ea 100644
--- a/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl
+++ b/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl
@@ -20,6 +20,8 @@
const int ERROR_GENERIC = 1;
/* Iface is no longer valid */
const int ERROR_IFACE_INVALID = 2;
+ /* Network being removed/retrieved does not exist */
+ const int ERROR_NETWORK_UNKNOWN = 3;
/**
* Retrieves the name of the network interface.
@@ -44,4 +46,16 @@
* @param id Network ID allocated to the corresponding network.
*/
void RemoveNetwork(in int id);
+
+ /**
+ * Gets a binder object for the network corresponding to the network_id.
+ *
+ * Use |INetwork.GetId()| on the corresponding network binder object
+ * to retrieve the ID.
+ *
+ * @param id Network ID allocated to the corresponding network.
+ *
+ * @return Binder object representing the network.
+ */
+ INetwork GetNetwork(in int id);
}
diff --git a/wpa_supplicant/binder/iface.cpp b/wpa_supplicant/binder/iface.cpp
index 6a3e223..267b90b 100644
--- a/wpa_supplicant/binder/iface.cpp
+++ b/wpa_supplicant/binder/iface.cpp
@@ -7,6 +7,7 @@
* See README for more details.
*/
+#include "binder_manager.h"
#include "iface.h"
namespace wpa_supplicant_binder {
@@ -34,11 +35,88 @@
android::binder::Status Iface::AddNetwork(
android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (!wpa_s) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_IFACE_INVALID,
+ "wpa_supplicant does not control this interface.");
+ }
+
+ struct wpa_ssid *ssid = wpa_config_add_network(wpa_s->conf);
+ if (!ssid) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_GENERIC, "wpa_supplicant couldn't add this network.");
+ }
+
+ // This sequence of steps after network addition is following what is
+ // currently being done in |ctrl_iface.c| & |dbus_new_handlers|.
+ // Notify the control interfaces about the network addition.
+ wpas_notify_network_added(wpa_s, ssid);
+ // Set the new network to be disabled.
+ ssid->disabled = 1;
+ // Set defaults for the new network.
+ wpa_config_set_network_defaults(ssid);
+
+ BinderManager *binder_manager = BinderManager::getInstance();
+ if (!binder_manager ||
+ binder_manager->getNetworkBinderObjectByIfnameAndNetworkId(
+ wpa_s->ifname, ssid->id, network_object_out)) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_GENERIC,
+ "wpa_supplicant encountered a binder error.");
+ }
return android::binder::Status::ok();
}
android::binder::Status Iface::RemoveNetwork(int network_id)
{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (!wpa_s) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_IFACE_INVALID,
+ "wpa_supplicant does not control this interface.");
+ }
+
+ struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, network_id);
+ if (!ssid) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_NETWORK_UNKNOWN,
+ "wpa_supplicant does not control this network.");
+ }
+ if (wpa_config_remove_network(wpa_s->conf, network_id)) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_GENERIC,
+ "wpa_supplicant couldn't remove this network.");
+ }
+ return android::binder::Status::ok();
+}
+
+android::binder::Status Iface::GetNetwork(
+ int network_id,
+ android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
+{
+ struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+ if (!wpa_s) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_IFACE_INVALID,
+ "wpa_supplicant does not control this interface.");
+ }
+
+ struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, network_id);
+ if (!ssid) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_NETWORK_UNKNOWN,
+ "wpa_supplicant does not control this network.");
+ }
+
+ BinderManager *binder_manager = BinderManager::getInstance();
+ if (!binder_manager ||
+ binder_manager->getNetworkBinderObjectByIfnameAndNetworkId(
+ wpa_s->ifname, ssid->id, network_object_out)) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_GENERIC,
+ "wpa_supplicant encountered a binder error.");
+ }
return android::binder::Status::ok();
}
diff --git a/wpa_supplicant/binder/iface.h b/wpa_supplicant/binder/iface.h
index bf8c6f0..13dd4b0 100644
--- a/wpa_supplicant/binder/iface.h
+++ b/wpa_supplicant/binder/iface.h
@@ -18,6 +18,8 @@
extern "C" {
#include "utils/common.h"
#include "utils/includes.h"
+#include "../config.h"
+#include "../notify.h"
#include "../wpa_supplicant_i.h"
}
@@ -40,6 +42,10 @@
android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
override;
android::binder::Status RemoveNetwork(int network_id) override;
+ android::binder::Status GetNetwork(
+ int network_id,
+ android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
+ override;
private:
struct wpa_supplicant *retrieveIfacePtr();
diff --git a/wpa_supplicant/binder/network.h b/wpa_supplicant/binder/network.h
index b8f3917..dfc1698 100644
--- a/wpa_supplicant/binder/network.h
+++ b/wpa_supplicant/binder/network.h
@@ -17,6 +17,7 @@
extern "C" {
#include "utils/common.h"
#include "utils/includes.h"
+#include "../config.h"
#include "../wpa_supplicant_i.h"
}
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 536f3e6..b2b4225 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -328,8 +328,10 @@
* applications since these network objects won't behave like
* regular ones.
*/
- if (!ssid->p2p_group && wpa_s->global->p2p_group_formation != wpa_s)
+ if (!ssid->p2p_group && wpa_s->global->p2p_group_formation != wpa_s) {
wpas_dbus_register_network(wpa_s, ssid);
+ wpas_binder_register_network(wpa_s, ssid);
+ }
}
@@ -359,8 +361,10 @@
if (wpa_s->wpa)
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
if (!ssid->p2p_group && wpa_s->global->p2p_group_formation != wpa_s &&
- !wpa_s->p2p_mgmt)
+ !wpa_s->p2p_mgmt) {
wpas_dbus_unregister_network(wpa_s, ssid->id);
+ wpas_binder_unregister_network(wpa_s, ssid);
+ }
if (network_is_persistent_group(ssid))
wpas_notify_persistent_group_removed(wpa_s, ssid);