Nexus: Clean up supplicant events, protocol, and continue plumbing
- Create SupplicantEvent classes for events
- New SupplicantEventFactory for creating events
- Extract Controller -> NetworkManager callbacks into IControllerHandler
- Move ScanResult handling from Supplicant -> WifiController
- Plumb more 'onConnected()' code
- Instead of re-creating NetworkList every-time, merge in
new entries
- Extract SupplicantListener -> Supplicant callbacks into
ISupplicantEventHandler
- Move SupplicantListener callback handling to WifiController
- Add unlocked version of lookupNetwork()
- Save supplicant config after setting a WifiNetwork variable
- Move property registration from WifiNetwork -> Supplicant
- Change wifi enable broadcast messages
- Add 3 new events: 'onAssociating', 'onAssociated', 'onConnectionTimeout'
- Add support for handling KeyManagement
Signed-off-by: San Mehat <san@google.com>
diff --git a/nexus/WifiController.cpp b/nexus/WifiController.cpp
index 3d06806..5c5db1a 100644
--- a/nexus/WifiController.cpp
+++ b/nexus/WifiController.cpp
@@ -27,34 +27,50 @@
#include "NetworkManager.h"
#include "ErrorCode.h"
#include "WifiNetwork.h"
+#include "ISupplicantEventHandler.h"
+#include "SupplicantState.h"
+#include "SupplicantStatus.h"
+#include "SupplicantAssociatingEvent.h"
+#include "SupplicantAssociatedEvent.h"
+#include "SupplicantConnectedEvent.h"
+#include "SupplicantScanResultsEvent.h"
+#include "SupplicantStateChangeEvent.h"
+#include "SupplicantConnectionTimeoutEvent.h"
+#include "SupplicantDisconnectedEvent.h"
-WifiController::WifiController(PropertyManager *propmngr, char *modpath, char *modname, char *modargs) :
- Controller("WIFI", propmngr) {
+WifiController::WifiController(PropertyManager *mPropMngr,
+ IControllerHandler *handlers,
+ char *modpath, char *modname, char *modargs) :
+ Controller("WIFI", mPropMngr, handlers) {
strncpy(mModulePath, modpath, sizeof(mModulePath));
strncpy(mModuleName, modname, sizeof(mModuleName));
strncpy(mModuleArgs, modargs, sizeof(mModuleArgs));
- mSupplicant = new Supplicant(this, propmngr);
+ mLatestScanResults = new ScanResultCollection();
+ pthread_mutex_init(&mLatestScanResultsLock, NULL);
+
+ mSupplicant = new Supplicant(this, this);
mScanner = new WifiScanner(mSupplicant, 10);
mCurrentScanMode = 0;
mEnabled = false;
- propmngr->registerProperty("wifi.enabled", this);
+ mSupplicantState = SupplicantState::UNKNOWN;
}
int WifiController::start() {
+ mPropMngr->registerProperty("wifi.enabled", this);
return 0;
}
int WifiController::stop() {
- errno = ENOSYS;
- return -1;
+ mPropMngr->unregisterProperty("wifi.enabled");
+ return 0;
}
int WifiController::enable() {
if (!isPoweredUp()) {
- sendStatusBroadcast("POWERING_UP");
+ sendStatusBroadcast("Powering up WiFi hardware");
if (powerUp()) {
LOGE("Powerup failed (%s)", strerror(errno));
return -1;
@@ -62,7 +78,7 @@
}
if (mModuleName[0] != '\0' && !isKernelModuleLoaded(mModuleName)) {
- sendStatusBroadcast("LOADING_DRIVER");
+ sendStatusBroadcast("Loading WiFi driver");
if (loadKernelModule(mModulePath, mModuleArgs)) {
LOGE("Kernel module load failed (%s)", strerror(errno));
goto out_powerdown;
@@ -70,7 +86,7 @@
}
if (!isFirmwareLoaded()) {
- sendStatusBroadcast("LOADING_FIRMWARE");
+ sendStatusBroadcast("Loading WiFI firmware");
if (loadFirmware()) {
LOGE("Firmware load failed (%s)", strerror(errno));
goto out_powerdown;
@@ -78,7 +94,7 @@
}
if (!mSupplicant->isStarted()) {
- sendStatusBroadcast("STARTING_SUPPLICANT");
+ sendStatusBroadcast("Starting WPA Supplicant");
if (mSupplicant->start()) {
LOGE("Supplicant start failed (%s)", strerror(errno));
goto out_unloadmodule;
@@ -93,6 +109,7 @@
if (mSupplicant->refreshNetworkList())
LOGW("Error getting list of networks (%s)", strerror(errno));
+ mPropMngr->registerProperty("wifi.supplicant.state", this);
mPropMngr->registerProperty("wifi.scanmode", this);
mPropMngr->registerProperty("wifi.interface", this);
@@ -121,8 +138,11 @@
int WifiController::disable() {
mPropMngr->unregisterProperty("wifi.scanmode");
+ mPropMngr->unregisterProperty("wifi.supplicant.state");
+ mPropMngr->unregisterProperty("wifi.scanmode");
+
if (mSupplicant->isStarted()) {
- sendStatusBroadcast("STOPPING_SUPPLICANT");
+ sendStatusBroadcast("Stopping WPA Supplicant");
if (mSupplicant->stop()) {
LOGE("Supplicant stop failed (%s)", strerror(errno));
return -1;
@@ -131,7 +151,7 @@
LOGW("disable(): Supplicant not running?");
if (mModuleName[0] != '\0' && isKernelModuleLoaded(mModuleName)) {
- sendStatusBroadcast("UNLOADING_DRIVER");
+ sendStatusBroadcast("Unloading WiFi driver");
if (unloadKernelModule(mModuleName)) {
LOGE("Unable to unload module (%s)", strerror(errno));
return -1;
@@ -139,7 +159,7 @@
}
if (isPoweredUp()) {
- sendStatusBroadcast("POWERING_DOWN");
+ sendStatusBroadcast("Powering down WiFi hardware");
if (powerDown()) {
LOGE("Powerdown failed (%s)", strerror(errno));
return -1;
@@ -184,7 +204,15 @@
}
ScanResultCollection *WifiController::createScanResults() {
- return mSupplicant->createLatestScanResults();
+ ScanResultCollection *d = new ScanResultCollection();
+ ScanResultCollection::iterator i;
+
+ pthread_mutex_lock(&mLatestScanResultsLock);
+ for (i = mLatestScanResults->begin(); i != mLatestScanResults->end(); ++i)
+ d->push_back((*i)->clone());
+
+ pthread_mutex_unlock(&mLatestScanResultsLock);
+ return d;
}
WifiNetworkCollection *WifiController::createNetworkList() {
@@ -207,7 +235,10 @@
return -1;
} else if (!strcmp(name, "wifi.scanmode"))
return setScanMode((uint32_t) strtoul(value, NULL, 0));
- else
+ else if (!strcmp(name, "wifi.supplicant.state")) {
+ errno = EROFS;
+ return -1;
+ } else
return Controller::set(name, value);
return rc;
}
@@ -221,9 +252,158 @@
(getBoundInterface() ? getBoundInterface() : "none"));
} else if (!strcmp(name, "wifi.scanmode"))
snprintf(buffer, maxsize, "0x%.8x", mCurrentScanMode);
+ else if (!strcmp(name, "wifi.supplicant.state"))
+ return SupplicantState::toString(mSupplicantState, buffer, maxsize);
else
return Controller::get(name, buffer, maxsize);
return buffer;
}
+void WifiController::onAssociatingEvent(SupplicantAssociatingEvent *evt) {
+ LOGD("onAssociatingEvent(%s, %s, %d)",
+ (evt->getBssid() ? evt->getBssid() : "n/a"),
+ (evt->getSsid() ? evt->getSsid() : "n/a"),
+ evt->getFreq());
+}
+
+void WifiController::onAssociatedEvent(SupplicantAssociatedEvent *evt) {
+ LOGD("onAssociatedEvent(%s)", evt->getBssid());
+}
+
+void WifiController::onConnectedEvent(SupplicantConnectedEvent *evt) {
+ LOGD("onConnectedEvent(%s, %d)", evt->getBssid(), evt->getReassociated());
+ if (!evt->getReassociated()) {
+ SupplicantStatus *ss = mSupplicant->getStatus();
+ WifiNetwork *wn;
+
+ if (ss->getWpaState() != SupplicantState::COMPLETED) {
+ char tmp[32];
+
+ LOGW("onConnected() with SupplicantState = %s!",
+ SupplicantState::toString(ss->getWpaState(), tmp,
+ sizeof(tmp)));
+ return;
+ }
+
+ if (ss->getId() == -1) {
+ LOGW("onConnected() with id = -1!");
+ return;
+ }
+
+ if (!(wn = mSupplicant->lookupNetwork(ss->getId()))) {
+ LOGW("Error looking up connected network id %d (%s)",
+ ss->getId(), strerror(errno));
+ return;
+ }
+
+ delete ss;
+ mHandlers->onInterfaceStarted(this, wn->getIfaceCfg());
+ }
+}
+
+void WifiController::onScanResultsEvent(SupplicantScanResultsEvent *evt) {
+ char *reply;
+
+ if (!(reply = (char *) malloc(4096))) {
+ LOGE("Out of memory");
+ return;
+ }
+
+ size_t len = 4096;
+
+ if (mSupplicant->sendCommand("SCAN_RESULTS", reply, &len)) {
+ LOGW("onScanResultsEvent: Error getting scan results (%s)",
+ strerror(errno));
+ free(reply);
+ return;
+ }
+
+ pthread_mutex_lock(&mLatestScanResultsLock);
+ if (!mLatestScanResults->empty()) {
+ ScanResultCollection::iterator i;
+
+ for (i = mLatestScanResults->begin();
+ i !=mLatestScanResults->end(); ++i) {
+ delete *i;
+ }
+ mLatestScanResults->clear();
+ }
+
+ char *linep;
+ char *linep_next = NULL;
+
+ if (!strtok_r(reply, "\n", &linep_next)) {
+ free(reply);
+ pthread_mutex_unlock(&mLatestScanResultsLock);
+ return;
+ }
+
+ while((linep = strtok_r(NULL, "\n", &linep_next)))
+ mLatestScanResults->push_back(new ScanResult(linep));
+
+ char *tmp;
+ asprintf(&tmp, "Scan results ready (%d)", mLatestScanResults->size());
+ NetworkManager::Instance()->getBroadcaster()->
+ sendBroadcast(ErrorCode::UnsolicitedInformational, tmp, false);
+ free(tmp);
+ pthread_mutex_unlock(&mLatestScanResultsLock);
+ free(reply);
+}
+
+void WifiController::onStateChangeEvent(SupplicantStateChangeEvent *evt) {
+ char tmp[32];
+ char tmp2[32];
+
+ LOGD("onStateChangeEvent(%s -> %s)",
+ SupplicantState::toString(mSupplicantState, tmp, sizeof(tmp)),
+ SupplicantState::toString(evt->getState(), tmp2, sizeof(tmp2)));
+
+ mSupplicantState = evt->getState();
+}
+
+void WifiController::onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent *evt) {
+ LOGD("onConnectionTimeoutEvent(%s)", evt->getBssid());
+}
+
+void WifiController::onDisconnectedEvent(SupplicantDisconnectedEvent *evt) {
+ LOGD("onDisconnectedEvent()");
+}
+
+#if 0
+void WifiController::onTerminatingEvent(SupplicantEvent *evt) {
+ LOGD("onTerminatingEvent(%s)", evt->getEvent());
+}
+
+void WifiController::onPasswordChangedEvent(SupplicantEvent *evt) {
+ LOGD("onPasswordChangedEvent(%s)", evt->getEvent());
+}
+
+void WifiController::onEapNotificationEvent(SupplicantEvent *evt) {
+ LOGD("onEapNotificationEvent(%s)", evt->getEvent());
+}
+
+void WifiController::onEapStartedEvent(SupplicantEvent *evt) {
+ LOGD("onEapStartedEvent(%s)", evt->getEvent());
+}
+
+void WifiController::onEapMethodEvent(SupplicantEvent *evt) {
+ LOGD("onEapMethodEvent(%s)", evt->getEvent());
+}
+
+void WifiController::onEapSuccessEvent(SupplicantEvent *evt) {
+ LOGD("onEapSuccessEvent(%s)", evt->getEvent());
+}
+
+void WifiController::onEapFailureEvent(SupplicantEvent *evt) {
+ LOGD("onEapFailureEvent(%s)", evt->getEvent());
+}
+
+void WifiController::onLinkSpeedEvent(SupplicantEvent *evt) {
+ LOGD("onLinkSpeedEvent(%s)", evt->getEvent());
+}
+
+void WifiController::onDriverStateEvent(SupplicantEvent *evt) {
+ LOGD("onDriverStateEvent(%s)", evt->getEvent());
+}
+#endif