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