binder: Add |INetwork| object interface

Create a new binder object interface to control networks. Neworks are
added/removed using the corresponding |IIface| binder object.

This CL only contains skeletal code for the new binder object.

While there,
Clean up the error codes in all the aid files and use the binder
exception codes to indicate INVALID_ARGS.

BUG: 30015382
Change-Id: I6953a623ab2c2b25f678d3b515a924a67d67d3fb
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 */