[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 &params,
+		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 &params,
+			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