summaryrefslogtreecommitdiffstats
path: root/libwifi_system
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2016-08-25 19:43:19 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2016-08-25 19:43:20 +0000
commit5d0e81f974deddce0d6fedceb57bff1f2c83a64e (patch)
treebbb4b8c59367bc8b21b34bd2dc56ef3386e0f28a /libwifi_system
parentc13a0778c3d9e081bb328bcea0bc64914de9b02e (diff)
parent8c784cd2472164c2bcbe33375c173f67247955eb (diff)
downloadandroid_frameworks_opt_net_wifi-5d0e81f974deddce0d6fedceb57bff1f2c83a64e.tar.gz
android_frameworks_opt_net_wifi-5d0e81f974deddce0d6fedceb57bff1f2c83a64e.tar.bz2
android_frameworks_opt_net_wifi-5d0e81f974deddce0d6fedceb57bff1f2c83a64e.zip
Merge "Move supplicant management functions to delegate"
Diffstat (limited to 'libwifi_system')
-rw-r--r--libwifi_system/Android.mk1
-rw-r--r--libwifi_system/include/wifi_system/supplicant_manager.h48
-rw-r--r--libwifi_system/include/wifi_system/wifi.h14
-rw-r--r--libwifi_system/supplicant_manager.cpp221
-rw-r--r--libwifi_system/testlib/include/wifi_system_test/mock_supplicant_manager.h38
-rw-r--r--libwifi_system/wifi.cpp187
6 files changed, 319 insertions, 190 deletions
diff --git a/libwifi_system/Android.mk b/libwifi_system/Android.mk
index 61d340a23..f969247e1 100644
--- a/libwifi_system/Android.mk
+++ b/libwifi_system/Android.mk
@@ -54,6 +54,7 @@ LOCAL_SRC_FILES := \
hostapd_manager.cpp \
interface_tool.cpp \
hal_tool.cpp \
+ supplicant_manager.cpp \
wifi.cpp
include $(BUILD_SHARED_LIBRARY)
diff --git a/libwifi_system/include/wifi_system/supplicant_manager.h b/libwifi_system/include/wifi_system/supplicant_manager.h
new file mode 100644
index 000000000..c666fc95a
--- /dev/null
+++ b/libwifi_system/include/wifi_system/supplicant_manager.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_WIFI_SYSTEM_SUPPLICANT_MANAGER_H
+#define ANDROID_WIFI_SYSTEM_SUPPLICANT_MANAGER_H
+
+#include <android-base/macros.h>
+
+namespace android {
+namespace wifi_system {
+
+class SupplicantManager {
+ public:
+ SupplicantManager() = default;
+ virtual ~SupplicantManager() = default;
+
+ // Request that supplicant be started.
+ // Returns true on success.
+ virtual bool StartSupplicant();
+
+ // Request that a running instance of supplicant be stopped.
+ // Returns true on success.
+ virtual bool StopSupplicant();
+
+ // Returns true iff supplicant is still running.
+ virtual bool IsSupplicantRunning();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SupplicantManager);
+}; // class SupplicantManager
+
+} // namespace wifi_system
+} // namespace android
+
+#endif // ANDROID_WIFI_SYSTEM_SUPPLICANT_MANAGER_H
diff --git a/libwifi_system/include/wifi_system/wifi.h b/libwifi_system/include/wifi_system/wifi.h
index 0cfbf3ee8..6d017ecc5 100644
--- a/libwifi_system/include/wifi_system/wifi.h
+++ b/libwifi_system/include/wifi_system/wifi.h
@@ -25,20 +25,6 @@ namespace wifi_system {
extern const char kWiFiEntropyFile[];
/**
- * Start supplicant.
- *
- * @return 0 on success, < 0 on failure.
- */
-int wifi_start_supplicant();
-
-/**
- * Stop supplicant.
- *
- * @return 0 on success, < 0 on failure.
- */
-int wifi_stop_supplicant();
-
-/**
* Open a connection to supplicant
*
* @return 0 on success, < 0 on failure.
diff --git a/libwifi_system/supplicant_manager.cpp b/libwifi_system/supplicant_manager.cpp
new file mode 100644
index 000000000..833739a05
--- /dev/null
+++ b/libwifi_system/supplicant_manager.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wifi_system/supplicant_manager.h"
+
+#include <android-base/logging.h>
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+// This ugliness is necessary to access internal implementation details
+// of the property subsystem.
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+// Certain system (emulators) don't have wpa_supplicant installed at all.
+#ifdef LIBWPA_CLIENT_EXISTS
+#include <libwpa_client/wpa_ctrl.h>
+#else
+void wpa_ctrl_cleanup(void) {}
+#endif
+
+#include "wifi_system/wifi.h"
+
+namespace android {
+namespace wifi_system {
+namespace {
+
+const char kSupplicantInitProperty[] = "init.svc.wpa_supplicant";
+const char kSupplicantConfigTemplatePath[] =
+ "/system/etc/wifi/wpa_supplicant.conf";
+const char kSupplicantConfigFile[] = "/data/misc/wifi/wpa_supplicant.conf";
+const char kP2pConfigFile[] = "/data/misc/wifi/p2p_supplicant.conf";
+const char kSupplicantServiceName[] = "wpa_supplicant";
+constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
+
+int ensure_config_file_exists(const char* config_file) {
+ char buf[2048];
+ int srcfd, destfd;
+ int nread;
+ int ret;
+
+ ret = access(config_file, R_OK | W_OK);
+ if ((ret == 0) || (errno == EACCES)) {
+ if ((ret != 0) && (chmod(config_file, kConfigFileMode) != 0)) {
+ LOG(ERROR) << "Cannot set RW to \"" << config_file << "\": "
+ << strerror(errno);
+ return false;
+ }
+ return true;
+ } else if (errno != ENOENT) {
+ LOG(ERROR) << "Cannot access \"" << config_file << "\": "
+ << strerror(errno);
+ return false;
+ }
+
+ srcfd = TEMP_FAILURE_RETRY(open(kSupplicantConfigTemplatePath, O_RDONLY));
+ if (srcfd < 0) {
+ LOG(ERROR) << "Cannot open \"" << kSupplicantConfigTemplatePath << "\": "
+ << strerror(errno);
+ return false;
+ }
+
+ destfd = TEMP_FAILURE_RETRY(open(config_file,
+ O_CREAT | O_RDWR,
+ kConfigFileMode));
+ if (destfd < 0) {
+ close(srcfd);
+ LOG(ERROR) << "Cannot create \"" << config_file << "\": "
+ << strerror(errno);
+ return false;
+ }
+
+ while ((nread = TEMP_FAILURE_RETRY(read(srcfd, buf, sizeof(buf)))) != 0) {
+ if (nread < 0) {
+ LOG(ERROR) << "Error reading \"" << kSupplicantConfigTemplatePath
+ << "\": " << strerror(errno);
+ close(srcfd);
+ close(destfd);
+ unlink(config_file);
+ return false;
+ }
+ TEMP_FAILURE_RETRY(write(destfd, buf, nread));
+ }
+
+ close(destfd);
+ close(srcfd);
+
+ /* chmod is needed because open() didn't set permisions properly */
+ if (chmod(config_file, kConfigFileMode) < 0) {
+ LOG(ERROR) << "Error changing permissions of " << config_file
+ << " to 0660: " << strerror(errno);
+ unlink(config_file);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace
+
+bool SupplicantManager::StartSupplicant() {
+ char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
+ int count = 200; /* wait at most 20 seconds for completion */
+ const prop_info* pi;
+ unsigned serial = 0;
+
+ /* Check whether already running */
+ if (property_get(kSupplicantInitProperty, supp_status, NULL) &&
+ strcmp(supp_status, "running") == 0) {
+ return true;
+ }
+
+ /* Before starting the daemon, make sure its config file exists */
+ if (ensure_config_file_exists(kSupplicantConfigFile) < 0) {
+ LOG(ERROR) << "Wi-Fi will not be enabled";
+ return false;
+ }
+
+ /*
+ * Some devices have another configuration file for the p2p interface.
+ * However, not all devices have this, and we'll let it slide if it
+ * is missing. For devices that do expect this file to exist,
+ * supplicant will refuse to start and emit a good error message.
+ * No need to check for it here.
+ */
+ (void)ensure_config_file_exists(kP2pConfigFile);
+
+ if (ensure_entropy_file_exists() < 0) {
+ LOG(ERROR) << "Wi-Fi entropy file was not created";
+ }
+
+ /* Clear out any stale socket files that might be left over. */
+ wpa_ctrl_cleanup();
+
+ /*
+ * Get a reference to the status property, so we can distinguish
+ * the case where it goes stopped => running => stopped (i.e.,
+ * it start up, but fails right away) from the case in which
+ * it starts in the stopped state and never manages to start
+ * running at all.
+ */
+ pi = __system_property_find(kSupplicantInitProperty);
+ if (pi != NULL) {
+ serial = __system_property_serial(pi);
+ }
+
+ property_set("ctl.start", kSupplicantServiceName);
+ sched_yield();
+
+ while (count-- > 0) {
+ if (pi == NULL) {
+ pi = __system_property_find(kSupplicantInitProperty);
+ }
+ if (pi != NULL) {
+ /*
+ * property serial updated means that init process is scheduled
+ * after we sched_yield, further property status checking is based on this
+ */
+ if (__system_property_serial(pi) != serial) {
+ __system_property_read(pi, NULL, supp_status);
+ if (strcmp(supp_status, "running") == 0) {
+ return true;
+ } else if (strcmp(supp_status, "stopped") == 0) {
+ return false;
+ }
+ }
+ }
+ usleep(100000);
+ }
+ return false;
+}
+
+bool SupplicantManager::StopSupplicant() {
+ char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
+ int count = 50; /* wait at most 5 seconds for completion */
+
+ /* Check whether supplicant already stopped */
+ if (property_get(kSupplicantInitProperty, supp_status, NULL) &&
+ strcmp(supp_status, "stopped") == 0) {
+ return true;
+ }
+
+ property_set("ctl.stop", kSupplicantServiceName);
+ sched_yield();
+
+ while (count-- > 0) {
+ if (property_get(kSupplicantInitProperty, supp_status, NULL)) {
+ if (strcmp(supp_status, "stopped") == 0) return true;
+ }
+ usleep(100000);
+ }
+ LOG(ERROR) << "Failed to stop supplicant";
+ return false;
+}
+
+bool SupplicantManager::IsSupplicantRunning() {
+ char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
+ if (property_get(kSupplicantInitProperty, supp_status, NULL)) {
+ return strcmp(supp_status, "running") == 0;
+ }
+ return false; // Failed to read service status from init.
+}
+
+} // namespace wifi_system
+} // namespace android
diff --git a/libwifi_system/testlib/include/wifi_system_test/mock_supplicant_manager.h b/libwifi_system/testlib/include/wifi_system_test/mock_supplicant_manager.h
new file mode 100644
index 000000000..01d604f47
--- /dev/null
+++ b/libwifi_system/testlib/include/wifi_system_test/mock_supplicant_manager.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_WIFI_SYSTEM_TEST_MOCK_SUPPLICANT_MANAGER_H
+#define ANDROID_WIFI_SYSTEM_TEST_MOCK_SUPPLICANT_MANAGER_H
+
+#include <wifi_system/supplicant_manager.h>
+
+namespace android {
+namespace wifi_system {
+
+class MockSupplicantManager : public SupplicantManager {
+ public:
+ ~MockSupplicantManager() override = default;
+
+ MOCK_METHOD0(StartSupplicant, bool());
+ MOCK_METHOD0(StopSupplicant, bool());
+ MOCK_METHOD0(IsSupplicantRunning, bool());
+
+}; // class MockSupplicantManager
+
+} // namespace wifi_system
+} // namespace android
+
+#endif // ANDROID_WIFI_SYSTEM_TEST_MOCK_SUPPLICANT_MANAGER_H
diff --git a/libwifi_system/wifi.cpp b/libwifi_system/wifi.cpp
index 49aee188b..e76a938e9 100644
--- a/libwifi_system/wifi.cpp
+++ b/libwifi_system/wifi.cpp
@@ -36,6 +36,8 @@
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
+#include "wifi_system/supplicant_manager.h"
+
#ifdef LIBWPA_CLIENT_EXISTS
#include <libwpa_client/wpa_ctrl.h>
#else
@@ -77,11 +79,6 @@ static char primary_iface[PROPERTY_VALUE_MAX];
#define WIFI_DRIVER_LOADER_DELAY 1000000
const char IFACE_DIR[] = "/data/system/wpa_supplicant";
-const char SUPPLICANT_SERVICE_NAME[] = "wpa_supplicant";
-const char SUPPLICANT_INIT_PROPERTY[] = "init.svc.wpa_supplicant";
-const char SUPP_CONFIG_TEMPLATE[] = "/system/etc/wifi/wpa_supplicant.conf";
-const char SUPP_CONFIG_FILE[] = "/data/misc/wifi/wpa_supplicant.conf";
-const char P2P_CONFIG_FILE[] = "/data/misc/wifi/p2p_supplicant.conf";
const char IFNAME[] = "IFNAME=";
#define IFNAMELEN (sizeof(IFNAME) - 1)
@@ -113,170 +110,16 @@ void wifi_close_sockets() {
}
}
-int ensure_config_file_exists(const char* config_file) {
- char buf[2048];
- int srcfd, destfd;
- int nread;
- int ret;
-
- ret = access(config_file, R_OK | W_OK);
- if ((ret == 0) || (errno == EACCES)) {
- if ((ret != 0) &&
- (chmod(config_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) != 0)) {
- ALOGE("Cannot set RW to \"%s\": %s", config_file, strerror(errno));
- return -1;
- }
- return 0;
- } else if (errno != ENOENT) {
- ALOGE("Cannot access \"%s\": %s", config_file, strerror(errno));
- return -1;
- }
-
- srcfd = TEMP_FAILURE_RETRY(open(SUPP_CONFIG_TEMPLATE, O_RDONLY));
- if (srcfd < 0) {
- ALOGE("Cannot open \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
- return -1;
- }
-
- destfd = TEMP_FAILURE_RETRY(open(config_file, O_CREAT | O_RDWR, 0660));
- if (destfd < 0) {
- close(srcfd);
- ALOGE("Cannot create \"%s\": %s", config_file, strerror(errno));
- return -1;
- }
-
- while ((nread = TEMP_FAILURE_RETRY(read(srcfd, buf, sizeof(buf)))) != 0) {
- if (nread < 0) {
- ALOGE("Error reading \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
- close(srcfd);
- close(destfd);
- unlink(config_file);
- return -1;
- }
- TEMP_FAILURE_RETRY(write(destfd, buf, nread));
- }
-
- close(destfd);
- close(srcfd);
-
- /* chmod is needed because open() didn't set permisions properly */
- if (chmod(config_file, 0660) < 0) {
- ALOGE("Error changing permissions of %s to 0660: %s", config_file,
- strerror(errno));
- unlink(config_file);
- return -1;
- }
-
- return 0;
-}
-
} // namespace
const char kWiFiEntropyFile[] = "/data/misc/wifi/entropy.bin";
-int wifi_start_supplicant() {
- char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
- int count = 200; /* wait at most 20 seconds for completion */
- const prop_info* pi;
- unsigned serial = 0;
-
- /* Check whether already running */
- if (property_get(SUPPLICANT_INIT_PROPERTY, supp_status, NULL) &&
- strcmp(supp_status, "running") == 0) {
- return 0;
- }
-
- /* Before starting the daemon, make sure its config file exists */
- if (ensure_config_file_exists(SUPP_CONFIG_FILE) < 0) {
- ALOGE("Wi-Fi will not be enabled");
- return -1;
- }
-
- /*
- * Some devices have another configuration file for the p2p interface.
- * However, not all devices have this, and we'll let it slide if it
- * is missing. For devices that do expect this file to exist,
- * supplicant will refuse to start and emit a good error message.
- * No need to check for it here.
- */
- (void)ensure_config_file_exists(P2P_CONFIG_FILE);
-
- if (ensure_entropy_file_exists() < 0) {
- ALOGE("Wi-Fi entropy file was not created");
- }
-
- /* Clear out any stale socket files that might be left over. */
- wpa_ctrl_cleanup();
-
- /*
- * Get a reference to the status property, so we can distinguish
- * the case where it goes stopped => running => stopped (i.e.,
- * it start up, but fails right away) from the case in which
- * it starts in the stopped state and never manages to start
- * running at all.
- */
- pi = __system_property_find(SUPPLICANT_INIT_PROPERTY);
- if (pi != NULL) {
- serial = __system_property_serial(pi);
- }
-
- property_set("ctl.start", SUPPLICANT_SERVICE_NAME);
- sched_yield();
-
- while (count-- > 0) {
- if (pi == NULL) {
- pi = __system_property_find(SUPPLICANT_INIT_PROPERTY);
- }
- if (pi != NULL) {
- /*
- * property serial updated means that init process is scheduled
- * after we sched_yield, further property status checking is based on this
- */
- if (__system_property_serial(pi) != serial) {
- __system_property_read(pi, NULL, supp_status);
- if (strcmp(supp_status, "running") == 0) {
- return 0;
- } else if (strcmp(supp_status, "stopped") == 0) {
- return -1;
- }
- }
- }
- usleep(100000);
- }
- return -1;
-}
-
-int wifi_stop_supplicant() {
- char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
- int count = 50; /* wait at most 5 seconds for completion */
-
- /* Check whether supplicant already stopped */
- if (property_get(SUPPLICANT_INIT_PROPERTY, supp_status, NULL) &&
- strcmp(supp_status, "stopped") == 0) {
- return 0;
- }
-
- property_set("ctl.stop", SUPPLICANT_SERVICE_NAME);
- sched_yield();
-
- while (count-- > 0) {
- if (property_get(SUPPLICANT_INIT_PROPERTY, supp_status, NULL)) {
- if (strcmp(supp_status, "stopped") == 0) return 0;
- }
- usleep(100000);
- }
- ALOGE("Failed to stop supplicant");
- return -1;
-}
-
namespace {
int wifi_connect_on_socket_path(const char* path) {
- char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
-
/* Make sure supplicant is running */
- if (!property_get(SUPPLICANT_INIT_PROPERTY, supp_status, NULL) ||
- strcmp(supp_status, "running") != 0) {
+ android::wifi_system::SupplicantManager manager;
+ if (!manager.IsSupplicantRunning()) {
ALOGE("Supplicant not running, cannot connect");
return -1;
}
@@ -331,20 +174,11 @@ int wifi_send_command(const char* cmd, char* reply, size_t* reply_len) {
return 0;
}
-int wifi_supplicant_connection_active() {
- char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
-
- if (property_get(SUPPLICANT_INIT_PROPERTY, supp_status, NULL)) {
- if (strcmp(supp_status, "stopped") == 0) return -1;
- }
-
- return 0;
-}
-
int wifi_ctrl_recv(char* reply, size_t* reply_len) {
int res;
int ctrlfd = wpa_ctrl_get_fd(monitor_conn);
struct pollfd rfds[2];
+ android::wifi_system::SupplicantManager manager;
memset(rfds, 0, 2 * sizeof(struct pollfd));
rfds[0].fd = ctrlfd;
@@ -360,8 +194,9 @@ int wifi_ctrl_recv(char* reply, size_t* reply_len) {
/* timed out, check if supplicant is active
* or not ..
*/
- res = wifi_supplicant_connection_active();
- if (res < 0) return -2;
+ if (!manager.IsSupplicantRunning()) {
+ return -2;
+ }
}
} while (res == 0);
@@ -467,15 +302,15 @@ int wifi_connect_to_supplicant() {
}
void wifi_close_supplicant_connection() {
- char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
int count =
50; /* wait at most 5 seconds to ensure init has stopped stupplicant */
wifi_close_sockets();
+ android::wifi_system::SupplicantManager manager;
while (count-- > 0) {
- if (property_get(SUPPLICANT_INIT_PROPERTY, supp_status, NULL)) {
- if (strcmp(supp_status, "stopped") == 0) return;
+ if (!manager.IsSupplicantRunning()) {
+ return;
}
usleep(100000);
}