Merge "p2p: p2p_go_ht40 won't take effect" into pi-dev
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index b4b0fea..54d12f6 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -46,11 +46,11 @@
 endif
 
 # Use Android specific directory for control interface sockets
-L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
-L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/system/hostapd\"
+L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/vendor/wifi/hostapd/sockets\"
+L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/vendor/wifi/hostapd/ctrl\"
 
 # Use Android specific directory for hostapd_cli command completion history
-L_CFLAGS += -DCONFIG_HOSTAPD_CLI_HISTORY_DIR=\"/data/misc/wifi\"
+L_CFLAGS += -DCONFIG_HOSTAPD_CLI_HISTORY_DIR=\"/data/vendor/wifi/hostapd\"
 
 # To force sizeof(enum) = 4
 ifeq ($(TARGET_ARCH),arm)
diff --git a/hostapd/hostapd.android.rc b/hostapd/hostapd.android.rc
index 70158c6..37a95c2 100644
--- a/hostapd/hostapd.android.rc
+++ b/hostapd/hostapd.android.rc
@@ -9,6 +9,7 @@
 on post-fs-data
     mkdir /data/vendor/wifi 0770 wifi wifi
     mkdir /data/vendor/wifi/hostapd 0770 wifi wifi
+    mkdir /data/vendor/wifi/hostapd/sockets 0770 wifi wifi
 
 service hostapd /vendor/bin/hw/hostapd
     interface android.hardware.wifi.hostapd@1.0::IHostapd default
diff --git a/wpa_supplicant/hidl/1.0/hidl_manager.cpp b/wpa_supplicant/hidl/1.0/hidl_manager.cpp
index 152203c..4655da2 100644
--- a/wpa_supplicant/hidl/1.0/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/1.0/hidl_manager.cpp
@@ -395,6 +395,10 @@
 	if (supplicant_object_->registerAsService() != android::NO_ERROR) {
 		return 1;
 	}
+	if (!supplicant_object_->ensureConfigFileExists()) {
+		// If config file does not exist, we cannot start supplicant.
+		return 1;
+	}
 	return 0;
 }
 
diff --git a/wpa_supplicant/hidl/1.0/supplicant.cpp b/wpa_supplicant/hidl/1.0/supplicant.cpp
index a381511..bf009b5 100644
--- a/wpa_supplicant/hidl/1.0/supplicant.cpp
+++ b/wpa_supplicant/hidl/1.0/supplicant.cpp
@@ -11,6 +11,110 @@
 #include "hidl_return_util.h"
 #include "supplicant.h"
 
+#include <android-base/file.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+namespace {
+constexpr char kStaIfaceConfPath[] =
+    "/data/misc/wifi/wpa_supplicant.conf";
+constexpr char kP2pIfaceConfPath[] =
+    "/data/misc/wifi/p2p_supplicant.conf";
+// Migrate conf files for existing devices.
+constexpr char kTemplateConfPath[] =
+    "/vendor/etc/wifi/wpa_supplicant.conf";
+constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
+
+int copyFile(
+    const std::string& src_file_path, const std::string& dest_file_path)
+{
+	std::string file_contents;
+	if (!android::base::ReadFileToString(src_file_path, &file_contents)) {
+		wpa_printf(
+		    MSG_ERROR, "Failed to read from %s. Errno: %s",
+		    src_file_path.c_str(), strerror(errno));
+		return -1;
+	}
+	if (!android::base::WriteStringToFile(
+		file_contents, dest_file_path, kConfigFileMode, getuid(),
+		getgid())) {
+		wpa_printf(
+		    MSG_ERROR, "Failed to write to %s. Errno: %s",
+		    dest_file_path.c_str(), strerror(errno));
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * Copy |src_file_path| to |dest_file_path| if it exists.
+ *
+ * Returns 1 if |src_file_path| does not exists,
+ * Returns -1 if the copy fails.
+ * Returns 0 if the copy succeeds.
+ */
+int copyFileIfItExists(
+    const std::string& src_file_path, const std::string& dest_file_path)
+{
+	int ret = access(src_file_path.c_str(), R_OK);
+	if ((ret != 0) && (errno == ENOENT)) {
+		return 1;
+	}
+	ret = copyFile(src_file_path, dest_file_path);
+	if (ret != 0) {
+		wpa_printf(
+		    MSG_ERROR, "Failed copying %s to %s.",
+		    src_file_path.c_str(), dest_file_path.c_str());
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * Ensure that the specified config file pointed by |config_file_path| exists.
+ * a) If the |config_file_path| exists with the correct permissions, return.
+ * b) If the |config_file_path| does not exists, copy over the contents of
+ * |template_config_file_path|.
+ */
+int copyTemplateConfigFileIfNotExists(
+    const std::string& config_file_path,
+    const std::string& template_config_file_path)
+{
+	int ret = access(config_file_path.c_str(), R_OK | W_OK);
+	if (ret == 0) {
+		return 0;
+	}
+	if (errno == EACCES) {
+		ret = chmod(config_file_path.c_str(), kConfigFileMode);
+		if (ret == 0) {
+			return 0;
+		} else {
+			wpa_printf(
+			    MSG_ERROR, "Cannot set RW to %s. Errno: %s",
+			    config_file_path.c_str(), strerror(errno));
+			return -1;
+		}
+	} else if (errno != ENOENT) {
+		wpa_printf(
+		    MSG_ERROR, "Cannot acces %s. Errno: %s",
+		    config_file_path.c_str(), strerror(errno));
+		return -1;
+	}
+	ret = copyFileIfItExists(template_config_file_path, config_file_path);
+	if (ret == 0) {
+		wpa_printf(
+		    MSG_INFO, "Copied template conf file from %s to %s",
+		    template_config_file_path.c_str(), config_file_path.c_str());
+		return 0;
+	} else if (ret == -1) {
+		unlink(config_file_path.c_str());
+		return -1;
+	}
+	// Did not create the conf file.
+	return -1;
+}
+}  // namespace
+
 namespace android {
 namespace hardware {
 namespace wifi {
@@ -31,6 +135,24 @@
 	return true;
 }
 
+bool Supplicant::ensureConfigFileExists()
+{
+	// To support Android P Wifi framework, make sure the config file exists.
+	if (copyTemplateConfigFileIfNotExists(
+		kStaIfaceConfPath, kTemplateConfPath) != 0) {
+		wpa_printf(MSG_ERROR, "Conf file does not exists: %s",
+		    kStaIfaceConfPath);
+		return false;
+	}
+	// P2P configuration file is not madatory but required for some devices.
+	if (copyTemplateConfigFileIfNotExists(
+		kP2pIfaceConfPath, kTemplateConfPath) != 0) {
+		wpa_printf(MSG_INFO, "Conf file does not exists: %s",
+		    kP2pIfaceConfPath);
+	}
+	return true;
+}
+
 Return<void> Supplicant::getInterface(
     const IfaceInfo& iface_info, getInterface_cb _hidl_cb)
 {
diff --git a/wpa_supplicant/hidl/1.0/supplicant.h b/wpa_supplicant/hidl/1.0/supplicant.h
index 1ad8402..04d1ae1 100644
--- a/wpa_supplicant/hidl/1.0/supplicant.h
+++ b/wpa_supplicant/hidl/1.0/supplicant.h
@@ -40,6 +40,7 @@
 	Supplicant(struct wpa_global* global);
 	~Supplicant() override = default;
 	bool isValid();
+	bool ensureConfigFileExists();
 
 	// Hidl methods exposed.
 	Return<void> getInterface(
diff --git a/wpa_supplicant/hidl/1.1/sta_network.cpp b/wpa_supplicant/hidl/1.1/sta_network.cpp
index e50927f..9d4cc91 100644
--- a/wpa_supplicant/hidl/1.1/sta_network.cpp
+++ b/wpa_supplicant/hidl/1.1/sta_network.cpp
@@ -1528,6 +1528,9 @@
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	wpa_s->scan_min_time.sec = 0;
 	wpa_s->scan_min_time.usec = 0;
+	// Make sure that the supplicant is updated to the latest
+	// MAC address, which might have changed due to MAC randomization.
+	wpa_supplicant_update_mac_addr(wpa_s);
 	wpa_supplicant_select_network(wpa_s, wpa_ssid);
 	return {SupplicantStatusCode::SUCCESS, ""};
 }