[PATCH 2/2] binder: Implement iface add/remove methods
Roshan Pius
rpius at google.com
Mon Jan 25 09:43:18 PST 2016
This CL implements the methods defined in Supplicant service:
1. CreateInterface
2. RemoveInterface
3. GetInterface
The binder service returns the corresponding iface binder object
references which can be used by clients to control a specific
interface.
BUG: 22957177
TEST: `mmm -j32 external/wpa_supplicant_8/wpa_supplicant` with
CONFIG_CTRL_IFACE_BINDER=y.
Change-Id: I086b1a17016eca13a9ce8759f63c048044e9f0f4
Signed-off-by: Roshan Pius <rpius at google.com>
---
wpa_supplicant/binder/binder.cpp | 27 ++++++
wpa_supplicant/binder/binder.h | 15 ++++
wpa_supplicant/binder/binder_manager.cpp | 51 +++++++++++
wpa_supplicant/binder/binder_manager.h | 5 ++
.../binder/fi/w1/wpa_supplicant/ISupplicant.aidl | 38 +++++++++
wpa_supplicant/binder/supplicant.cpp | 99 ++++++++++++++++++++++
wpa_supplicant/binder/supplicant.h | 10 +++
wpa_supplicant/wpa_supplicant_i.h | 3 +
8 files changed, 248 insertions(+)
diff --git a/wpa_supplicant/binder/binder.cpp b/wpa_supplicant/binder/binder.cpp
index 580f585..4419d7b 100644
--- a/wpa_supplicant/binder/binder.cpp
+++ b/wpa_supplicant/binder/binder.cpp
@@ -84,3 +84,30 @@ void wpas_binder_deinit(struct wpas_binder_priv *priv)
eloop_unregister_read_sock(priv->binder_fd);
android::IPCThreadState::shutdown();
}
+
+int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->global->binder == NULL)
+ return 1;
+
+ wpa_supplicant_binder::BinderManager *binder_manager =
+ wpa_supplicant_binder::BinderManager::getInstance();
+ if (binder_manager == NULL)
+ return 1;
+
+ return binder_manager->registerInterface(wpa_s);
+}
+
+int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->global->binder == NULL)
+ return 1;
+
+ wpa_supplicant_binder::BinderManager *binder_manager =
+ wpa_supplicant_binder::BinderManager::getInstance();
+ if (binder_manager == NULL)
+ return 1;
+
+ return binder_manager->unregisterInterface(wpa_s);
+}
+
diff --git a/wpa_supplicant/binder/binder.h b/wpa_supplicant/binder/binder.h
index eb7b70f..8444ac5 100644
--- a/wpa_supplicant/binder/binder.h
+++ b/wpa_supplicant/binder/binder.h
@@ -32,6 +32,21 @@ struct wpa_global;
struct wpas_binder_priv * wpas_binder_init(struct wpa_global *global);
void wpas_binder_deinit(struct wpas_binder_priv *priv);
+#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);
+
+#else /* CONFIG_CTRL_IFACE_BINDER */
+static inline int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
+{
+ return 0;
+}
+static inline int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+ return 0;
+}
+#endif /* CONFIG_CTRL_IFACE_BINDER */
+
#ifdef _cplusplus
}
#endif /* _cplusplus */
diff --git a/wpa_supplicant/binder/binder_manager.cpp b/wpa_supplicant/binder/binder_manager.cpp
index eb2d60b..f57002d 100644
--- a/wpa_supplicant/binder/binder_manager.cpp
+++ b/wpa_supplicant/binder/binder_manager.cpp
@@ -53,4 +53,55 @@ int BinderManager::registerBinderService(struct wpa_global *global)
return 0;
}
+int BinderManager::registerInterface(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s == NULL)
+ return 1;
+
+ // Using the corresponding wpa_supplicant pointer as key to our
+ // object map.
+ const void *iface_key = wpa_s;
+
+ // Return failure if we already have an object for that iface_key.
+ if (iface_object_map_.find(iface_key) != iface_object_map_.end())
+ return 1;
+
+ iface_object_map_[iface_key] = new Iface(wpa_s);
+ if (iface_object_map_[iface_key].get() == NULL)
+ return 1;
+
+ wpa_s->binder_object_key = iface_key;
+
+ return 0;
+}
+
+int BinderManager::unregisterInterface(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s == NULL || wpa_s->binder_object_key == NULL)
+ return 1;
+
+ const void *iface_key = wpa_s;
+ if (iface_object_map_.find(iface_key) == iface_object_map_.end())
+ return 1;
+
+ // Delete the corresponding iface object from our map.
+ iface_object_map_.erase(iface_key);
+ wpa_s->binder_object_key = NULL;
+ return 0;
+}
+
+int BinderManager::getIfaceBinderObjectByKey(
+ const void *iface_object_key,
+ android::sp<fi::w1::wpa_supplicant::IIface> *iface_object)
+{
+ if (iface_object_key == NULL || iface_object == NULL)
+ return 1;
+
+ if (iface_object_map_.find(iface_object_key) == iface_object_map_.end())
+ return 1;
+
+ *iface_object = iface_object_map_[iface_object_key];
+ return 0;
+}
+
} // namespace wpa_supplicant_binder
diff --git a/wpa_supplicant/binder/binder_manager.h b/wpa_supplicant/binder/binder_manager.h
index 7b9d95f..8021c0e 100644
--- a/wpa_supplicant/binder/binder_manager.h
+++ b/wpa_supplicant/binder/binder_manager.h
@@ -40,6 +40,11 @@ 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 getIfaceBinderObjectByKey(
+ const void *iface_object_key,
+ android::sp<fi::w1::wpa_supplicant::IIface> *iface_object);
private:
BinderManager() = default;
diff --git a/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl b/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl
index 889663d..67d4e2f 100644
--- a/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl
+++ b/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl
@@ -17,10 +17,48 @@
package fi.w1.wpa_supplicant;
import android.os.PersistableBundle;
+import fi.w1.wpa_supplicant.IIface;
/**
* Interface exposed by the wpa_supplicant binder service registered
* with the service manager with name: fi.w1.wpa_supplicant.
*/
interface ISupplicant {
+ /* Error values returned by the service to RPC method calls. */
+ const int ERROR_INVALID_ARGS = 1;
+ const int ERROR_UNKNOWN = 2;
+ const int ERROR_IFACE_EXISTS = 3;
+ const int ERROR_IFACE_UNKNOWN = 4;
+
+ /**
+ * Registers a wireless interface in wpa_supplicant.
+ *
+ * @param args A dictionary with arguments used to add the interface to
+ * wpa_supplicant.
+ * The dictionary may contain the following entries:
+ * Ifname(String) Name of the network interface to control, e.g., wlan0.
+ * BridgeIfname(String) Name of the bridge interface to control, e.g., br0.
+ * Driver(String) Driver name which the interface uses, e.g., nl80211.
+ * ConfigFile(String) Configuration file path.
+ *
+ * @return Binder object representing the interface.
+ */
+ IIface CreateInterface(in PersistableBundle args);
+
+ /**
+ * Deregisters a wireless interface from wpa_supplicant.
+ *
+ * @param ifname Name of the network interface, e.g., wlan0
+ */
+ void RemoveInterface(in String ifname);
+
+ /**
+ * Gets a binder object for the interface corresponding to ifname
+ * which wpa_supplicant already controls.
+ *
+ * @param ifname Name of the network interface, e.g., wlan0
+ *
+ * @return Binder object representing the interface.
+ */
+ IIface GetInterface(in String ifname);
}
diff --git a/wpa_supplicant/binder/supplicant.cpp b/wpa_supplicant/binder/supplicant.cpp
index 8eafcb7..be02142 100644
--- a/wpa_supplicant/binder/supplicant.cpp
+++ b/wpa_supplicant/binder/supplicant.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "binder_manager.h"
#include "supplicant.h"
namespace wpa_supplicant_binder {
@@ -23,4 +24,102 @@ Supplicant::Supplicant(struct wpa_global *global)
{
}
+android::binder::Status Supplicant::CreateInterface(
+ const android::os::PersistableBundle ¶ms,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
+{
+ android::String16 driver, ifname, confname, bridge_ifname;
+
+ /* Check if Required Ifname argument is missing */
+ if (!params.getString(android::String16("Ifname"), &ifname))
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_INVALID_ARGS, android::String8("Ifname missing in params."));
+ /* Retrieve the remaining params from the dictionary */
+ params.getString(android::String16("Driver"), &driver);
+ params.getString(android::String16("ConfigFile"), &confname);
+ params.getString(android::String16("BridgeIfname"), &bridge_ifname);
+
+ /*
+ * Try to get the wpa_supplicant record for this iface, return
+ * an error if we already control it.
+ */
+ if (wpa_supplicant_get_iface(
+ wpa_global_, android::String8(ifname).string()) != NULL)
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_IFACE_EXISTS,
+ android::String8("wpa_supplicant already controls this interface."));
+
+ android::binder::Status status;
+ struct wpa_supplicant *wpa_s = NULL;
+ struct wpa_interface iface;
+
+ os_memset(&iface, 0, sizeof(iface));
+ iface.driver = strdup(android::String8(driver).string());
+ iface.ifname = strdup(android::String8(ifname).string());
+ iface.confname = strdup(android::String8(confname).string());
+ iface.bridge_ifname = strdup(android::String8(bridge_ifname).string());
+ /* Otherwise, have wpa_supplicant attach to it. */
+ wpa_s = wpa_supplicant_add_iface(wpa_global_, &iface, NULL);
+ // The supplicant core creates a corresponding binder object via
+ // BinderManager when |wpa_supplicant_add_iface| is called.
+ if (wpa_s == NULL || wpa_s->binder_object_key == NULL)
+ status = android::binder::Status::fromServiceSpecificError(
+ ERROR_UNKNOWN,
+ android::String8("wpa_supplicant couldn't grab this interface."));
+ else {
+ BinderManager *binder_manager = BinderManager::getInstance();
+ if (binder_manager == NULL ||
+ binder_manager->getIfaceBinderObjectByKey(
+ wpa_s->binder_object_key, aidl_return))
+ status = android::binder::Status::fromServiceSpecificError(
+ ERROR_UNKNOWN,
+ android::String8("wpa_supplicant encountered a binder error."));
+ else
+ status = android::binder::Status::ok();
+ }
+ os_free((void *)iface.driver);
+ os_free((void *)iface.ifname);
+ os_free((void *)iface.confname);
+ os_free((void *)iface.bridge_ifname);
+ return status;
+}
+
+android::binder::Status Supplicant::RemoveInterface(
+ const android::String16 &ifname)
+{
+ struct wpa_supplicant *wpa_s = NULL;
+ wpa_s = wpa_supplicant_get_iface(
+ wpa_global_, android::String8(ifname).string());
+ if (wpa_s == NULL || wpa_s->binder_object_key == NULL)
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_IFACE_UNKNOWN,
+ android::String8("wpa_supplicant does not control this interface."));
+ else if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0))
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_UNKNOWN,
+ android::String8("wpa_supplicant couldn't remove this interface."));
+ return android::binder::Status::ok();
+}
+
+android::binder::Status Supplicant::GetInterface(
+ const android::String16 &ifname,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
+{
+ struct wpa_supplicant *wpa_s = NULL;
+ wpa_s = wpa_supplicant_get_iface(
+ wpa_global_, android::String8(ifname).string());
+ if (wpa_s == NULL || wpa_s->binder_object_key == NULL)
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_IFACE_UNKNOWN,
+ android::String8("wpa_supplicant does not control this interface."));
+ BinderManager *binder_manager = BinderManager::getInstance();
+ if (binder_manager == NULL ||
+ binder_manager->getIfaceBinderObjectByKey(
+ wpa_s->binder_object_key, aidl_return))
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_UNKNOWN,
+ android::String8("wpa_supplicant encountered a binder error."));
+ return android::binder::Status::ok();
+}
+
} // namespace wpa_supplicant_binder
diff --git a/wpa_supplicant/binder/supplicant.h b/wpa_supplicant/binder/supplicant.h
index c5858f8..22ad038 100644
--- a/wpa_supplicant/binder/supplicant.h
+++ b/wpa_supplicant/binder/supplicant.h
@@ -18,6 +18,7 @@
#define SUPPLICANT_H
#include "fi/w1/wpa_supplicant/BnSupplicant.h"
+#include "fi/w1/wpa_supplicant/IIface.h"
#include "fi/w1/wpa_supplicant/ISupplicantCallbacks.h"
extern "C" {
@@ -38,6 +39,15 @@ public:
Supplicant(struct wpa_global *global);
virtual ~Supplicant() = default;
+ android::binder::Status CreateInterface(
+ const android::os::PersistableBundle ¶ms,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) override;
+ android::binder::Status RemoveInterface(
+ const android::String16 &ifname) override;
+ android::binder::Status GetInterface(
+ const android::String16 &ifname,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) override;
+
private:
// Raw pointer to the global structure maintained by the core.
struct wpa_global *wpa_global_;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index d049e8a..267accc 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -465,6 +465,9 @@ struct wpa_supplicant {
char *preq_notify_peer;
#endif /* CONFIG_AP */
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
+#ifdef CONFIG_CTRL_IFACE_BINDER
+ const void *binder_object_key;
+#endif /* CONFIG_CTRL_IFACE_BINDER */
char bridge_ifname[16];
char *confname;
--
2.7.0.rc3.207.g0ac5344
More information about the Hostap
mailing list