binder: Implement iface methods

Implement the following iface methods:
1. Reassociate
2. Reconnect
3. Disconnct

BUG: 30093041
Change-Id: I83a527a06c89f05e693212c536f21494c678843e
TEST: Writing new tests in |wpa_supplicant_binder_test|
Signed-off-by: Roshan Pius <rpius@google.com>
diff --git a/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl b/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl
index da8d130..f05d086 100644
--- a/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl
+++ b/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl
@@ -21,8 +21,12 @@
 	const int ERROR_GENERIC = 1;
 	/* Iface is no longer valid */
 	const int ERROR_IFACE_INVALID = 2;
+	/* Iface is currently disabled */
+	const int ERROR_IFACE_DISABLED = 3;
+	/* Iface is currently connected */
+	const int ERROR_IFACE_NOT_DISCONNECTED = 4;
 	/* Network being removed/retrieved does not exist */
-	const int ERROR_NETWORK_UNKNOWN = 3;
+	const int ERROR_NETWORK_UNKNOWN = 5;
 
 	/**
 	 * Retrieves the name of the network interface.
@@ -69,4 +73,22 @@
 	 *        instance.
 	 */
 	void RegisterCallback(in IIfaceCallback callback);
+
+	/**
+	 * Reconnect to the currently active network, even if we are already
+	 * connected.
+	 */
+	void Reassociate();
+
+	/**
+	 * Reconnect to the currently active network, if we are currently
+	 * disconnected.
+	 */
+	void Reconnect();
+
+	/**
+	 * Disconnect from the current active network.
+	 */
+	void Disconnect();
+
 }
diff --git a/wpa_supplicant/binder/iface.cpp b/wpa_supplicant/binder/iface.cpp
index 280e191..cd4be06 100644
--- a/wpa_supplicant/binder/iface.cpp
+++ b/wpa_supplicant/binder/iface.cpp
@@ -121,6 +121,49 @@
 	return android::binder::Status::ok();
 }
 
+android::binder::Status Iface::Reassociate()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return android::binder::Status::fromServiceSpecificError(
+		    ERROR_IFACE_DISABLED);
+	}
+	wpas_request_connection(wpa_s);
+	return android::binder::Status::ok();
+}
+
+android::binder::Status Iface::Reconnect()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return android::binder::Status::fromServiceSpecificError(
+		    ERROR_IFACE_DISABLED);
+	}
+	if (!wpa_s->disconnected) {
+		return android::binder::Status::fromServiceSpecificError(
+		    ERROR_IFACE_NOT_DISCONNECTED);
+	}
+	wpas_request_connection(wpa_s);
+	return android::binder::Status::ok();
+}
+
+android::binder::Status Iface::Disconnect()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return android::binder::Status::fromServiceSpecificError(
+		    ERROR_IFACE_DISABLED);
+	}
+	wpas_request_disconnection(wpa_s);
+	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 50d7d80..5a727f0 100644
--- a/wpa_supplicant/binder/iface.h
+++ b/wpa_supplicant/binder/iface.h
@@ -47,6 +47,9 @@
 	android::binder::Status RegisterCallback(
 	    const android::sp<fi::w1::wpa_supplicant::IIfaceCallback> &callback)
 	    override;
+	android::binder::Status Reassociate() override;
+	android::binder::Status Reconnect() override;
+	android::binder::Status Disconnect() override;
 
 private:
 	struct wpa_supplicant *retrieveIfacePtr();