binder: Add |INetwork| object interface
am: d6e375115b

Change-Id: Ic98f1b103620cbf09a6c326091b1c222a2431370
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 0c52f0c..5ca994e 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -1655,9 +1655,10 @@
     $(LOCAL_PATH)/binder/include
 LOCAL_SRC_FILES := \
     binder/binder_constants.cpp \
+    binder/fi/w1/wpa_supplicant/IIface.aidl \
+    binder/fi/w1/wpa_supplicant/INetwork.aidl \
     binder/fi/w1/wpa_supplicant/ISupplicant.aidl \
-    binder/fi/w1/wpa_supplicant/ISupplicantCallbacks.aidl \
-    binder/fi/w1/wpa_supplicant/IIface.aidl
+    binder/fi/w1/wpa_supplicant/ISupplicantCallbacks.aidl
 LOCAL_SHARED_LIBRARIES := libbinder
 LOCAL_EXPORT_C_INCLUDE_DIRS := \
     $(LOCAL_PATH)/binder/include
diff --git a/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl b/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl
index fb77ffa..dd0fbaa 100644
--- a/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl
+++ b/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl
@@ -9,20 +9,39 @@
 
 package fi.w1.wpa_supplicant;
 
+import fi.w1.wpa_supplicant.INetwork;
+
 /**
  * Interface exposed by wpa_supplicant for each network interface it controls.
  */
 @utf8InCpp
 interface IIface {
-	/* 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_UNKNOWN = 3;
+	/* Non-specific error encountered */
+	const int ERROR_GENERIC = 1;
+	/* Iface is no longer valid */
+	const int ERROR_IFACE_INVALID = 2;
 
 	/**
-	 * Retrieves the name of the iface this object controls.
+	 * Retrieves the name of the network interface.
 	 *
 	 * @return Name of the network interface, e.g., wlan0
 	 */
 	String GetName();
+
+	/**
+	 * Add a new network to the interface.
+	 *
+	 * @return Binder object representing the new network.
+	 */
+	INetwork AddNetwork();
+
+	/**
+	 * Remove a network from the interface.
+	 *
+	 * Use |INetwork.GetId()| on the corresponding network binder object
+	 * to retrieve the ID.
+	 *
+	 * @param id Network ID allocated to the corresponding network.
+	 */
+	void RemoveNetwork(in int id);
 }
diff --git a/wpa_supplicant/binder/fi/w1/wpa_supplicant/INetwork.aidl b/wpa_supplicant/binder/fi/w1/wpa_supplicant/INetwork.aidl
new file mode 100644
index 0000000..74aa9ad
--- /dev/null
+++ b/wpa_supplicant/binder/fi/w1/wpa_supplicant/INetwork.aidl
@@ -0,0 +1,41 @@
+/*
+ * binder 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.
+ */
+
+package fi.w1.wpa_supplicant;
+
+/**
+ * Interface exposed by wpa_supplicant for each network configuration it controls.
+ * A network is wpa_supplicant's way of representing the configuration parameters of a Wifi
+ * service set. Service sets are identified by their service set identitifier (SSID).
+ * The parameters for a network includes the credentials, bssid, etc.
+ */
+@utf8InCpp
+interface INetwork {
+	/* Non-specific error encountered */
+	const int ERROR_GENERIC = 1;
+	/* Network is no longer valid */
+	const int ERROR_NETWORK_INVALID = 2;
+
+	/**
+	 * Retrieves the ID allocated to this network by wpa_supplicant.
+	 *
+	 * This is not the |SSID| of the network, but an internal identifier for
+	 * this network used by wpa_supplicant.
+	 *
+	 * @return network ID.
+	 */
+	int GetId();
+
+	/**
+	 * Retrieves the name of the interface this network belongs to.
+	 *
+	 * @return Name of the network interface, e.g., wlan0
+	 */
+	String GetInterfaceName();
+}
diff --git a/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl b/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl
index a52f857..7e353a0 100644
--- a/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl
+++ b/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl
@@ -18,11 +18,12 @@
  */
 @utf8InCpp
 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;
+	/* Non-specific error encountered */
+	const int ERROR_GENERIC = 1;
+	/* Iface being added already exists */
+	const int ERROR_IFACE_EXISTS = 2;
+	/* Iface being removed/retrieved does not exist */
+	const int ERROR_IFACE_UNKNOWN = 3;
 
 	/**
 	 * Registers a wireless interface in wpa_supplicant.
diff --git a/wpa_supplicant/binder/iface.cpp b/wpa_supplicant/binder/iface.cpp
index 4faa147..6a3e223 100644
--- a/wpa_supplicant/binder/iface.cpp
+++ b/wpa_supplicant/binder/iface.cpp
@@ -23,7 +23,7 @@
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	if (!wpa_s) {
 		return android::binder::Status::fromServiceSpecificError(
-		    ERROR_IFACE_UNKNOWN,
+		    ERROR_IFACE_INVALID,
 		    "wpa_supplicant does not control this interface.");
 	}
 
@@ -31,6 +31,17 @@
 	return android::binder::Status::ok();
 }
 
+android::binder::Status Iface::AddNetwork(
+    android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
+{
+	return android::binder::Status::ok();
+}
+
+android::binder::Status Iface::RemoveNetwork(int network_id)
+{
+	return android::binder::Status::ok();
+}
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct pointer for
  * this iface.
diff --git a/wpa_supplicant/binder/iface.h b/wpa_supplicant/binder/iface.h
index f87f19f..bf8c6f0 100644
--- a/wpa_supplicant/binder/iface.h
+++ b/wpa_supplicant/binder/iface.h
@@ -10,7 +10,10 @@
 #ifndef WPA_SUPPLICANT_BINDER_IFACE_H
 #define WPA_SUPPLICANT_BINDER_IFACE_H
 
+#include <android-base/macros.h>
+
 #include "fi/w1/wpa_supplicant/BnIface.h"
+#include "fi/w1/wpa_supplicant/INetwork.h"
 
 extern "C" {
 #include "utils/common.h"
@@ -29,19 +32,25 @@
 {
 public:
 	Iface(struct wpa_global *wpa_global, const char ifname[]);
-	virtual ~Iface() = default;
+	~Iface() override = default;
 
 	// Binder methods exposed in aidl.
 	android::binder::Status GetName(std::string *iface_name_out) override;
+	android::binder::Status AddNetwork(
+	    android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
+	    override;
+	android::binder::Status RemoveNetwork(int network_id) override;
 
 private:
+	struct wpa_supplicant *retrieveIfacePtr();
+
 	// Reference to the global wpa_struct. This is assumed to be valid for
 	// the lifetime of the process.
 	const struct wpa_global *wpa_global_;
 	// Name of the iface this binder object controls
 	const std::string ifname_;
 
-	struct wpa_supplicant *retrieveIfacePtr();
+	DISALLOW_COPY_AND_ASSIGN(Iface);
 };
 
 } // namespace wpa_supplicant_binder
diff --git a/wpa_supplicant/binder/network.cpp b/wpa_supplicant/binder/network.cpp
new file mode 100644
index 0000000..5a87ca1
--- /dev/null
+++ b/wpa_supplicant/binder/network.cpp
@@ -0,0 +1,61 @@
+/*
+ * binder 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 "network.h"
+
+namespace wpa_supplicant_binder {
+
+Network::Network(
+    struct wpa_global *wpa_global, const char ifname[], int network_id)
+    : wpa_global_(wpa_global), ifname_(ifname), network_id_(network_id)
+{
+}
+
+android::binder::Status Network::GetId(int *network_id_out)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid) {
+		return android::binder::Status::fromServiceSpecificError(
+		    ERROR_NETWORK_INVALID,
+		    "wpa_supplicant does not control this network.");
+	}
+
+	*network_id_out = network_id_;
+	return android::binder::Status::ok();
+}
+
+android::binder::Status Network::GetInterfaceName(std::string *ifname_out)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid) {
+		return android::binder::Status::fromServiceSpecificError(
+		    ERROR_NETWORK_INVALID,
+		    "wpa_supplicant does not control this network.");
+	}
+
+	*ifname_out = ifname_;
+	return android::binder::Status::ok();
+}
+
+/**
+ * Retrieve the underlying |wpa_ssid| struct pointer for
+ * this network.
+ * If the underlying network is removed or the interface this network belong to
+ * is removed, all RPC method calls on this object will return failure.
+ */
+struct wpa_ssid *Network::retrieveNetworkPtr()
+{
+	wpa_supplicant *wpa_s = wpa_supplicant_get_iface(
+	    (struct wpa_global *)wpa_global_, ifname_.c_str());
+	if (!wpa_s)
+		return nullptr;
+	return wpa_config_get_network(wpa_s->conf, network_id_);
+}
+
+} // namespace wpa_supplicant_binder
diff --git a/wpa_supplicant/binder/network.h b/wpa_supplicant/binder/network.h
new file mode 100644
index 0000000..b8f3917
--- /dev/null
+++ b/wpa_supplicant/binder/network.h
@@ -0,0 +1,58 @@
+/*
+ * binder 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.
+ */
+
+#ifndef WPA_SUPPLICANT_BINDER_NETWORK_H
+#define WPA_SUPPLICANT_BINDER_NETWORK_H
+
+#include <android-base/macros.h>
+
+#include "fi/w1/wpa_supplicant/BnNetwork.h"
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "../wpa_supplicant_i.h"
+}
+
+namespace wpa_supplicant_binder {
+
+/**
+ * Implementation of Network binder object. Each unique binder
+ * object is used for control operations on a specific network
+ * controlled by wpa_supplicant.
+ */
+class Network : public fi::w1::wpa_supplicant::BnNetwork
+{
+public:
+	Network(
+	    struct wpa_global *wpa_global, const char ifname[], int network_id);
+	~Network() override = default;
+
+	// Binder methods exposed in aidl.
+	android::binder::Status GetId(int *network_id_out) override;
+	android::binder::Status
+	GetInterfaceName(std::string *ifname_out) override;
+
+private:
+	struct wpa_ssid *retrieveNetworkPtr();
+
+	// Reference to the global wpa_struct. This is assumed to be valid for
+	// the lifetime of the process.
+	const struct wpa_global *wpa_global_;
+	// Name of the iface this network belongs to.
+	const std::string ifname_;
+	// Id of the network this binder object controls.
+	const int network_id_;
+
+	DISALLOW_COPY_AND_ASSIGN(Network);
+};
+
+} // namespace wpa_supplicant_binder
+
+#endif // WPA_SUPPLICANT_BINDER_NETWORK_H
diff --git a/wpa_supplicant/binder/supplicant.cpp b/wpa_supplicant/binder/supplicant.cpp
index 76569b1..d85f2cf 100644
--- a/wpa_supplicant/binder/supplicant.cpp
+++ b/wpa_supplicant/binder/supplicant.cpp
@@ -22,9 +22,9 @@
 
 	/* 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."));
+		return android::binder::Status::fromExceptionCode(
+		    android::binder::Status::EX_ILLEGAL_ARGUMENT,
+		    "Ifname missing in params.");
 	/* Retrieve the remaining params from the dictionary */
 	params.getString(android::String16("Driver"), &driver);
 	params.getString(android::String16("ConfigFile"), &confname);
@@ -38,8 +38,7 @@
 		wpa_global_, android::String8(ifname).string()) != NULL)
 		return android::binder::Status::fromServiceSpecificError(
 		    ERROR_IFACE_EXISTS,
-		    android::String8("wpa_supplicant already controls this "
-				     "interface."));
+		    "wpa_supplicant already controls this interface.");
 
 	android::binder::Status status;
 	struct wpa_supplicant *wpa_s = NULL;
@@ -57,9 +56,8 @@
 	 * BinderManager when |wpa_supplicant_add_iface| is called. */
 	if (!wpa_s || !wpa_s->binder_object_key) {
 		status = android::binder::Status::fromServiceSpecificError(
-		    ERROR_UNKNOWN,
-		    android::String8(
-			"wpa_supplicant couldn't grab this interface."));
+		    ERROR_GENERIC,
+		    "wpa_supplicant couldn't grab this interface.");
 	} else {
 		BinderManager *binder_manager = BinderManager::getInstance();
 
@@ -68,9 +66,8 @@
 			wpa_s->binder_object_key, aidl_return))
 			status =
 			    android::binder::Status::fromServiceSpecificError(
-				ERROR_UNKNOWN,
-				android::String8("wpa_supplicant encountered a "
-						 "binder error."));
+				ERROR_GENERIC,
+				"wpa_supplicant encountered a binder error.");
 		else
 			status = android::binder::Status::ok();
 	}
@@ -89,13 +86,11 @@
 	if (!wpa_s || !wpa_s->binder_object_key)
 		return android::binder::Status::fromServiceSpecificError(
 		    ERROR_IFACE_UNKNOWN,
-		    android::String8("wpa_supplicant does not control this "
-				     "interface."));
+		    "wpa_supplicant does not control this interface.");
 	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."));
+		    ERROR_GENERIC,
+		    "wpa_supplicant couldn't remove this interface.");
 	return android::binder::Status::ok();
 }
 
@@ -109,17 +104,15 @@
 	if (!wpa_s || !wpa_s->binder_object_key)
 		return android::binder::Status::fromServiceSpecificError(
 		    ERROR_IFACE_UNKNOWN,
-		    android::String8(
-			"wpa_supplicant does not control this interface."));
+		    "wpa_supplicant does not control this interface.");
 
 	BinderManager *binder_manager = BinderManager::getInstance();
 	if (!binder_manager ||
 	    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."));
+		    ERROR_GENERIC,
+		    "wpa_supplicant encountered a binder error.");
 
 	return android::binder::Status::ok();
 }
diff --git a/wpa_supplicant/binder/supplicant.h b/wpa_supplicant/binder/supplicant.h
index 136b99b..5b5fafa 100644
--- a/wpa_supplicant/binder/supplicant.h
+++ b/wpa_supplicant/binder/supplicant.h
@@ -10,6 +10,8 @@
 #ifndef WPA_SUPPLICANT_BINDER_SUPPLICANT_H
 #define WPA_SUPPLICANT_BINDER_SUPPLICANT_H
 
+#include <android-base/macros.h>
+
 #include "fi/w1/wpa_supplicant/BnSupplicant.h"
 #include "fi/w1/wpa_supplicant/IIface.h"
 #include "fi/w1/wpa_supplicant/ISupplicantCallbacks.h"
@@ -31,7 +33,7 @@
 {
 public:
 	Supplicant(struct wpa_global *global);
-	virtual ~Supplicant() = default;
+	~Supplicant() override = default;
 
 	android::binder::Status CreateInterface(
 	    const android::os::PersistableBundle &params,
@@ -48,6 +50,8 @@
 	/* All the callback objects registered by the clients. */
 	std::vector<android::sp<fi::w1::wpa_supplicant::ISupplicantCallbacks>>
 	    callbacks_;
+
+	DISALLOW_COPY_AND_ASSIGN(Supplicant);
 };
 
 } /* namespace wpa_supplicant_binder */