binder: Implement enable/disable/select network

Implement the following control methods:
1. EnableNetwork
2. DisableNetwork
3. SelectNetwork

BUG: 1252274
Change-Id: I61042baed83088d61a2946eb5a1205df30ff2518
TEST: Ran 'wpa_supplicant_binder_test'
Signed-off-by: Roshan Pius <rpius@google.com>
diff --git a/wpa_supplicant/binder/network.cpp b/wpa_supplicant/binder/network.cpp
index 6e14328..5f7d06c 100644
--- a/wpa_supplicant/binder/network.cpp
+++ b/wpa_supplicant/binder/network.cpp
@@ -233,6 +233,17 @@
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
 	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (wpa_ssid->disabled == 2) {
+		return android::binder::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "Cannot use Select with persistent P2P group");
+	}
+
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_s->scan_min_time.sec = 0;
+	wpa_s->scan_min_time.usec = 0;
+	wpa_supplicant_select_network(wpa_s, wpa_ssid);
 	return android::binder::Status::ok();
 }
 
@@ -240,6 +251,15 @@
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
 	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (wpa_ssid->disabled == 2) {
+		return android::binder::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "Cannot use Disable with persistent P2P group");
+	}
+
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_supplicant_disable_network(wpa_s, wpa_ssid);
 	return android::binder::Status::ok();
 }
 
@@ -247,6 +267,21 @@
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
 	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (wpa_ssid->disabled == 2) {
+		return android::binder::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "Cannot use Enable with persistent P2P group");
+	}
+
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (no_connect) {
+		wpa_ssid->disabled = 0;
+	} else {
+		wpa_s->scan_min_time.sec = 0;
+		wpa_s->scan_min_time.usec = 0;
+		wpa_supplicant_enable_network(wpa_s, wpa_ssid);
+	}
 	return android::binder::Status::ok();
 }
 
@@ -258,11 +293,19 @@
  */
 struct wpa_ssid *Network::retrieveNetworkPtr()
 {
-	wpa_supplicant *wpa_s = wpa_supplicant_get_iface(
-	    (struct wpa_global *)wpa_global_, ifname_.c_str());
+	wpa_supplicant *wpa_s = retrieveIfacePtr();
 	if (!wpa_s)
 		return nullptr;
 	return wpa_config_get_network(wpa_s->conf, network_id_);
 }
 
+/**
+ * Retrieve the underlying |wpa_supplicant| struct pointer for
+ * this network.
+ */
+struct wpa_supplicant *Network::retrieveIfacePtr()
+{
+	return wpa_supplicant_get_iface(
+	    (struct wpa_global *)wpa_global_, ifname_.c_str());
+}
 } // namespace wpa_supplicant_binder
diff --git a/wpa_supplicant/binder/network.h b/wpa_supplicant/binder/network.h
index 8a28aae..1717597 100644
--- a/wpa_supplicant/binder/network.h
+++ b/wpa_supplicant/binder/network.h
@@ -82,6 +82,7 @@
 
 private:
 	struct wpa_ssid *retrieveNetworkPtr();
+	struct wpa_supplicant *retrieveIfacePtr();
 
 	// Reference to the global wpa_struct. This is assumed to be valid for
 	// the lifetime of the process.