wifi: Restructure wifi legacy HAL implementation

Restructured the existing code to create a new class called
|WifiLegacyHal|. This class will be used as a wrapper to invoke
all the legacy HAL functions and handle the "C" style callbacks.

Bug: 31936700
Test: mmma -j32 hardware/interfaces/wifi/1.0/default
Change-Id: I63e8543f49886f8446101320a97d1e96e30d1035
diff --git a/wifi/1.0/default/Android.mk b/wifi/1.0/default/Android.mk
index 6180efd..14923f5 100644
--- a/wifi/1.0/default/Android.mk
+++ b/wifi/1.0/default/Android.mk
@@ -21,7 +21,7 @@
     failure_reason_util.cpp \
     wifi_chip.cpp \
     wifi.cpp \
-    wifi_hal_state.cpp
+    wifi_legacy_hal.cpp
 LOCAL_SHARED_LIBRARIES := \
     android.hardware.wifi@1.0 \
     libbase \
diff --git a/wifi/1.0/default/service.cpp b/wifi/1.0/default/service.cpp
index 07e6c81..10ce1db 100644
--- a/wifi/1.0/default/service.cpp
+++ b/wifi/1.0/default/service.cpp
@@ -55,13 +55,14 @@
 
   // Setup hwbinder service
   android::sp<android::hardware::wifi::V1_0::IWifi> service =
-      new android::hardware::wifi::V1_0::implementation::Wifi(looper);
+      new android::hardware::wifi::V1_0::implementation::Wifi();
   CHECK_EQ(service->registerAsService("wifi"), android::NO_ERROR)
       << "Failed to register wifi HAL";
 
   // Loop
-  while (looper->pollAll(-1) != Looper::POLL_ERROR)
-    ;
+  while (looper->pollAll(-1) != Looper::POLL_ERROR) {
+    // Keep polling until failure.
+  }
 
   LOG(INFO) << "wifi_hal_legacy is terminating...";
   return 0;
diff --git a/wifi/1.0/default/wifi.cpp b/wifi/1.0/default/wifi.cpp
index aa0fc5b..d5b69b8 100644
--- a/wifi/1.0/default/wifi.cpp
+++ b/wifi/1.0/default/wifi.cpp
@@ -17,31 +17,18 @@
 #include "wifi.h"
 
 #include <android-base/logging.h>
-#include <cutils/properties.h>
 
 #include "failure_reason_util.h"
 #include "wifi_chip.h"
 
-using RunState = ::android::hardware::wifi::WifiHalState::RunState;
-
-namespace {
-std::string GetWlanInterfaceName() {
-  char buffer[PROPERTY_VALUE_MAX];
-  property_get("wifi.interface", buffer, "wlan0");
-  return buffer;
-}
-}
-
 namespace android {
 namespace hardware {
 namespace wifi {
 namespace V1_0 {
 namespace implementation {
 
-Wifi::Wifi(sp<Looper>& looper) : state_(looper) {
-  CHECK_EQ(init_wifi_vendor_hal_func_table(&state_.func_table_), WIFI_SUCCESS)
-      << "Failed to initialize hal func table";
-}
+Wifi::Wifi()
+    : legacy_hal_(new WifiLegacyHal()), run_state_(RunState::STOPPED) {}
 
 Return<void> Wifi::registerEventCallback(
     const sp<IWifiEventCallback>& callback) {
@@ -51,131 +38,76 @@
 }
 
 Return<bool> Wifi::isStarted() {
-  return state_.run_state_ != RunState::STOPPED;
+  return run_state_ != RunState::STOPPED;
 }
 
 Return<void> Wifi::start() {
-  if (state_.run_state_ == RunState::STARTED) {
-    for (auto& callback : callbacks_) {
+  if (run_state_ == RunState::STARTED) {
+    for (const auto& callback : callbacks_) {
       callback->onStart();
     }
     return Void();
-  } else if (state_.run_state_ == RunState::STOPPING) {
-    for (auto& callback : callbacks_) {
+  } else if (run_state_ == RunState::STOPPING) {
+    for (const auto& callback : callbacks_) {
       callback->onStartFailure(CreateFailureReason(
           CommandFailureReason::NOT_AVAILABLE, "HAL is stopping"));
     }
     return Void();
   }
 
-  LOG(INFO) << "Initializing HAL";
-  wifi_error status = state_.func_table_.wifi_initialize(&state_.hal_handle_);
+  LOG(INFO) << "Starting HAL";
+  wifi_error status = legacy_hal_->start();
   if (status != WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to initialize Wifi HAL";
+    LOG(ERROR) << "Failed to start Wifi HAL";
     for (auto& callback : callbacks_) {
       callback->onStartFailure(
-          CreateFailureReasonLegacyError(status, "Failed to initialize HAL"));
+          CreateFailureReasonLegacyError(status, "Failed to start HAL"));
     }
     return Void();
   }
 
-  event_loop_thread_ = std::thread(&Wifi::DoHalEventLoop, this);
-
-  wifi_interface_handle iface_handle =
-      FindInterfaceHandle(GetWlanInterfaceName());
-  if (iface_handle != kInterfaceNotFoundHandle) {
-    chip_ = new WifiChip(&state_, iface_handle);
-  } else {
-    // TODO fail to init?
-  }
-
-  state_.run_state_ = RunState::STARTED;
-  for (auto& callback : callbacks_) {
+  // Create the chip instance once the HAL is started.
+  chip_ = new WifiChip(legacy_hal_);
+  run_state_ = RunState::STARTED;
+  for (const auto& callback : callbacks_) {
     callback->onStart();
   }
   return Void();
 }
 
-wifi_interface_handle Wifi::FindInterfaceHandle(const std::string& ifname) {
-  int num_iface_handles = 0;
-  wifi_interface_handle* iface_handles = nullptr;
-  wifi_error ret = state_.func_table_.wifi_get_ifaces(
-      state_.hal_handle_, &num_iface_handles, &iface_handles);
-  if (ret != WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to enumerate interface handles: "
-               << LegacyErrorToString(ret);
-    return kInterfaceNotFoundHandle;
-  }
-
-  char buffer[IFNAMSIZ];
-  for (int i = 0; i < num_iface_handles; ++i) {
-    bzero(buffer, sizeof(buffer));
-    ret = state_.func_table_.wifi_get_iface_name(
-        iface_handles[i], buffer, sizeof(buffer));
-    if (ret != WIFI_SUCCESS) {
-      LOG(WARNING) << "Failed to get interface handle name: "
-                   << LegacyErrorToString(ret);
-      continue;
-    }
-    if (ifname == buffer) {
-      return iface_handles[i];
-    }
-  }
-  return kInterfaceNotFoundHandle;
-}
-
-void NoopHalCleanupHandler(wifi_handle) {}
-
 Return<void> Wifi::stop() {
-  if (state_.run_state_ == RunState::STOPPED) {
-    for (auto& callback : callbacks_) {
+  if (run_state_ == RunState::STOPPED) {
+    for (const auto& callback : callbacks_) {
       callback->onStop();
     }
     return Void();
-  } else if (state_.run_state_ == RunState::STOPPING) {
+  } else if (run_state_ == RunState::STOPPING) {
     return Void();
   }
 
-  LOG(INFO) << "Cleaning up HAL";
-  awaiting_hal_cleanup_command_ = true;
-  awaiting_hal_event_loop_termination_ = true;
-  state_.run_state_ = RunState::STOPPING;
-
-  if (chip_.get())
-    chip_->Invalidate();
-  chip_.clear();
-
-  state_.func_table_.wifi_cleanup(state_.hal_handle_, NoopHalCleanupHandler);
-  awaiting_hal_cleanup_command_ = false;
-  LOG(VERBOSE) << "HAL cleanup command complete";
-  FinishHalCleanup();
+  LOG(INFO) << "Stopping HAL";
+  run_state_ = RunState::STOPPING;
+  const auto on_complete_callback_ = [&]() {
+    if (chip_.get()) {
+      chip_->invalidate();
+    }
+    chip_.clear();
+    run_state_ = RunState::STOPPED;
+    for (const auto& callback : callbacks_) {
+      callback->onStop();
+    }
+  };
+  wifi_error status = legacy_hal_->stop(on_complete_callback_);
+  if (status != WIFI_SUCCESS) {
+    LOG(ERROR) << "Failed to stop Wifi HAL";
+    for (const auto& callback : callbacks_) {
+      callback->onFailure(
+          CreateFailureReasonLegacyError(status, "Failed to stop HAL"));
+    }
+  }
   return Void();
 }
 
-void Wifi::DoHalEventLoop() {
-  LOG(VERBOSE) << "Starting HAL event loop";
-  state_.func_table_.wifi_event_loop(state_.hal_handle_);
-  if (state_.run_state_ != RunState::STOPPING) {
-    LOG(FATAL) << "HAL event loop terminated, but HAL was not stopping";
-  }
-  LOG(VERBOSE) << "HAL Event loop terminated";
-  event_loop_thread_.detach();
-  state_.PostTask([this]() {
-    awaiting_hal_event_loop_termination_ = false;
-    FinishHalCleanup();
-  });
-}
-
-void Wifi::FinishHalCleanup() {
-  if (!awaiting_hal_cleanup_command_ && !awaiting_hal_event_loop_termination_) {
-    state_.run_state_ = RunState::STOPPED;
-    LOG(INFO) << "HAL cleanup complete";
-    for (auto& callback : callbacks_) {
-      callback->onStop();
-    }
-  }
-}
-
 Return<void> Wifi::getChip(getChip_cb cb) {
   cb(chip_);
   return Void();
diff --git a/wifi/1.0/default/wifi.h b/wifi/1.0/default/wifi.h
index 0122741..e6cf1ac 100644
--- a/wifi/1.0/default/wifi.h
+++ b/wifi/1.0/default/wifi.h
@@ -19,15 +19,13 @@
 
 #include <functional>
 #include <set>
-#include <thread>
 
 #include <android-base/macros.h>
 #include <android/hardware/wifi/1.0/IWifi.h>
-#include <hardware_legacy/wifi_hal.h>
 #include <utils/Looper.h>
 
-#include "wifi_hal_state.h"
 #include "wifi_chip.h"
+#include "wifi_legacy_hal.h"
 
 namespace android {
 namespace hardware {
@@ -35,45 +33,31 @@
 namespace V1_0 {
 namespace implementation {
 
+/**
+ * Root HIDL interface object used to control the Wifi HAL.
+ */
 class Wifi : public IWifi {
  public:
-  Wifi(sp<Looper>& looper);
+  Wifi();
 
+  // HIDL methods exposed.
   Return<void> registerEventCallback(
       const sp<IWifiEventCallback>& callback) override;
-
   Return<bool> isStarted() override;
   Return<void> start() override;
   Return<void> stop() override;
-
   Return<void> getChip(getChip_cb cb) override;
 
  private:
-  const wifi_interface_handle kInterfaceNotFoundHandle = nullptr;
-  /** Get a HAL interface handle by name */
-  wifi_interface_handle FindInterfaceHandle(const std::string& ifname);
+  enum class RunState { STOPPED, STARTED, STOPPING };
 
-  /**
-   * Called to indicate that the HAL implementation cleanup may be complete and
-   * the rest of HAL cleanup should be performed.
-   */
-  void FinishHalCleanup();
-
-  /**
-   * Entry point for HAL event loop thread. Handles cleanup when terminating.
-   */
-  void DoHalEventLoop();
-
+  // Instance is created in this root level |IWifi| HIDL interface object
+  // and shared with all the child HIDL interface objects.
+  std::shared_ptr<WifiLegacyHal> legacy_hal_;
+  RunState run_state_;
   std::set<sp<IWifiEventCallback>> callbacks_;
   sp<WifiChip> chip_;
 
-  WifiHalState state_;
-  std::thread event_loop_thread_;
-
-  // Variables to hold state while stopping the HAL
-  bool awaiting_hal_cleanup_command_;
-  bool awaiting_hal_event_loop_termination_;
-
   DISALLOW_COPY_AND_ASSIGN(Wifi);
 };
 
diff --git a/wifi/1.0/default/wifi_chip.cpp b/wifi/1.0/default/wifi_chip.cpp
index 42118b7..91cf514 100644
--- a/wifi/1.0/default/wifi_chip.cpp
+++ b/wifi/1.0/default/wifi_chip.cpp
@@ -26,18 +26,17 @@
 namespace V1_0 {
 namespace implementation {
 
-WifiChip::WifiChip(WifiHalState* hal_state,
-                   wifi_interface_handle interface_handle)
-    : hal_state_(hal_state), interface_handle_(interface_handle) {}
+WifiChip::WifiChip(std::weak_ptr<WifiLegacyHal> legacy_hal)
+    : legacy_hal_(legacy_hal) {}
 
-void WifiChip::Invalidate() {
-  hal_state_ = nullptr;
+void WifiChip::invalidate() {
+  legacy_hal_.reset();
   callbacks_.clear();
 }
 
 Return<void> WifiChip::registerEventCallback(
     const sp<IWifiChipEventCallback>& callback) {
-  if (!hal_state_)
+  if (!legacy_hal_.lock())
     return Void();
   // TODO(b/31632518): remove the callback when the client is destroyed
   callbacks_.insert(callback);
@@ -45,7 +44,7 @@
 }
 
 Return<void> WifiChip::getAvailableModes(getAvailableModes_cb cb) {
-  if (!hal_state_) {
+  if (!legacy_hal_.lock()) {
     cb(hidl_vec<ChipMode>());
     return Void();
   } else {
@@ -55,54 +54,23 @@
 }
 
 Return<void> WifiChip::configureChip(uint32_t /*mode_id*/) {
-  if (!hal_state_)
+  if (!legacy_hal_.lock())
     return Void();
   // TODO add implementation
   return Void();
 }
 
 Return<uint32_t> WifiChip::getMode() {
-  if (!hal_state_)
+  if (!legacy_hal_.lock())
     return 0;
   // TODO add implementation
   return 0;
 }
 
 Return<void> WifiChip::requestChipDebugInfo() {
-  if (!hal_state_)
+  if (!legacy_hal_.lock())
     return Void();
-
-  IWifiChipEventCallback::ChipDebugInfo result;
-  result.driverDescription = "<unknown>";
-  result.firmwareDescription = "<unknown>";
-  char buffer[256];
-
-  // get driver version
-  bzero(buffer, sizeof(buffer));
-  wifi_error ret = hal_state_->func_table_.wifi_get_driver_version(
-      interface_handle_, buffer, sizeof(buffer));
-  if (ret == WIFI_SUCCESS) {
-    result.driverDescription = buffer;
-  } else {
-    LOG(WARNING) << "Failed to get driver version: "
-                 << LegacyErrorToString(ret);
-  }
-
-  // get firmware version
-  bzero(buffer, sizeof(buffer));
-  ret = hal_state_->func_table_.wifi_get_firmware_version(
-      interface_handle_, buffer, sizeof(buffer));
-  if (ret == WIFI_SUCCESS) {
-    result.firmwareDescription = buffer;
-  } else {
-    LOG(WARNING) << "Failed to get firmware version: "
-                 << LegacyErrorToString(ret);
-  }
-
-  // send callback
-  for (auto& callback : callbacks_) {
-    callback->onChipDebugInfoAvailable(result);
-  }
+  // TODO add implementation
   return Void();
 }
 
diff --git a/wifi/1.0/default/wifi_chip.h b/wifi/1.0/default/wifi_chip.h
index d776644..95fabe4 100644
--- a/wifi/1.0/default/wifi_chip.h
+++ b/wifi/1.0/default/wifi_chip.h
@@ -21,9 +21,8 @@
 
 #include <android-base/macros.h>
 #include <android/hardware/wifi/1.0/IWifiChip.h>
-#include <hardware_legacy/wifi_hal.h>
 
-#include "wifi_hal_state.h"
+#include "wifi_legacy_hal.h"
 
 namespace android {
 namespace hardware {
@@ -31,30 +30,29 @@
 namespace V1_0 {
 namespace implementation {
 
+/**
+ * HIDL interface object used to control a Wifi HAL chip instance.
+ * Since there is only a single chip instance used today, there is no
+ * identifying handle information stored here.
+ */
 class WifiChip : public IWifiChip {
  public:
-  WifiChip(WifiHalState* hal_state, wifi_interface_handle interface_handle);
+  WifiChip(std::weak_ptr<WifiLegacyHal> legacy_hal);
+  // Invalidate this instance once the HAL is stopped.
+  void invalidate();
 
-  void Invalidate();
-
+  // HIDL methods exposed.
   Return<void> registerEventCallback(
       const sp<IWifiChipEventCallback>& callback) override;
-
   Return<void> getAvailableModes(getAvailableModes_cb cb) override;
-
   Return<void> configureChip(uint32_t mode_id) override;
-
   Return<uint32_t> getMode() override;
-
   Return<void> requestChipDebugInfo() override;
-
   Return<void> requestDriverDebugDump() override;
-
   Return<void> requestFirmwareDebugDump() override;
 
  private:
-  WifiHalState* hal_state_;
-  wifi_interface_handle interface_handle_;
+  std::weak_ptr<WifiLegacyHal> legacy_hal_;
   std::set<sp<IWifiChipEventCallback>> callbacks_;
 
   DISALLOW_COPY_AND_ASSIGN(WifiChip);
diff --git a/wifi/1.0/default/wifi_hal_state.cpp b/wifi/1.0/default/wifi_hal_state.cpp
deleted file mode 100644
index 1483689..0000000
--- a/wifi/1.0/default/wifi_hal_state.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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_hal_state.h"
-
-#include <android-base/logging.h>
-#include <hardware_legacy/wifi_hal.h>
-#include <utils/Looper.h>
-
-namespace {
-class FunctionMessageHandler : public android::MessageHandler {
- public:
-  explicit FunctionMessageHandler(const std::function<void()>& callback)
-      : callback_(callback) {}
-
-  ~FunctionMessageHandler() override = default;
-
-  virtual void handleMessage(const android::Message& /*message*/) {
-    callback_();
-  }
-
- private:
-  const std::function<void()> callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(FunctionMessageHandler);
-};
-}
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_0 {
-namespace implementation {
-
-WifiHalState::WifiHalState(sp<Looper>& looper)
-    : run_state_(RunState::STOPPED), looper_(looper) {}
-
-void WifiHalState::PostTask(const std::function<void()>& callback) {
-  sp<MessageHandler> message_handler = new FunctionMessageHandler(callback);
-  looper_->sendMessage(message_handler, NULL);
-}
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.0/default/wifi_hal_state.h b/wifi/1.0/default/wifi_hal_state.h
deleted file mode 100644
index 40e39ec..0000000
--- a/wifi/1.0/default/wifi_hal_state.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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 WIFI_HAL_LEGACY_WIFI_HAL_STATE_H_
-#define WIFI_HAL_LEGACY_WIFI_HAL_STATE_H_
-
-#include <functional>
-
-#include <android-base/macros.h>
-#include <hardware_legacy/wifi_hal.h>
-#include <utils/Looper.h>
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_0 {
-namespace implementation {
-
-/**
- * Class that stores common state and functionality shared between HAL services.
- */
-class WifiHalState {
- public:
-  WifiHalState(sp<Looper>& looper);
-
-  /** Post a task to be executed on the main thread */
-  void PostTask(const std::function<void()>& callback);
-
-  wifi_hal_fn func_table_;
-  /** opaque handle from vendor for use while HAL is running */
-  wifi_handle hal_handle_;
-
-  enum class RunState { STOPPED, STARTED, STOPPING };
-
-  RunState run_state_;
-
- private:
-  sp<Looper> looper_;
-
-  DISALLOW_COPY_AND_ASSIGN(WifiHalState);
-};
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WIFI_HAL_LEGACY_WIFI_HAL_STATE_H_
diff --git a/wifi/1.0/default/wifi_legacy_hal.cpp b/wifi/1.0/default/wifi_legacy_hal.cpp
new file mode 100644
index 0000000..a9ad0d1
--- /dev/null
+++ b/wifi/1.0/default/wifi_legacy_hal.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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 <array>
+
+#include "failure_reason_util.h"
+#include "wifi_legacy_hal.h"
+
+#include <android-base/logging.h>
+#include <cutils/properties.h>
+
+namespace {
+std::string getWlanInterfaceName() {
+  char buffer[PROPERTY_VALUE_MAX];
+  property_get("wifi.interface", buffer, "wlan0");
+  return buffer;
+}
+
+// Legacy HAL functions accept "C" style function pointers, so use global
+// functions to pass to the legacy HAL function and store the corresponding
+// std::function methods to be invoked.
+// Callback to be invoked once |stop| is complete.
+std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
+void onStopComplete(wifi_handle handle) {
+  if (on_stop_complete_internal_callback) {
+    on_stop_complete_internal_callback(handle);
+  }
+}
+}
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_0 {
+namespace implementation {
+
+WifiLegacyHal::WifiLegacyHal()
+    : global_handle_(nullptr),
+      wlan_interface_handle_(nullptr),
+      awaiting_event_loop_termination_(false) {
+  CHECK_EQ(init_wifi_vendor_hal_func_table(&global_func_table_), WIFI_SUCCESS)
+      << "Failed to initialize legacy hal function table";
+}
+
+wifi_error WifiLegacyHal::start() {
+  // Ensure that we're starting in a good state.
+  CHECK(!global_handle_ && !wlan_interface_handle_ &&
+        !awaiting_event_loop_termination_);
+
+  LOG(INFO) << "Starting legacy HAL";
+  wifi_error status = global_func_table_.wifi_initialize(&global_handle_);
+  if (status != WIFI_SUCCESS || !global_handle_) {
+    LOG(ERROR) << "Failed to retrieve global handle";
+    return status;
+  }
+  event_loop_thread_ = std::thread(&WifiLegacyHal::runEventLoop, this);
+  status = retrieveWlanInterfaceHandle();
+  if (status != WIFI_SUCCESS || !wlan_interface_handle_) {
+    LOG(ERROR) << "Failed to retrieve wlan interface handle";
+    return status;
+  }
+  LOG(VERBOSE) << "Legacy HAL start complete";
+  return WIFI_SUCCESS;
+}
+
+wifi_error WifiLegacyHal::stop(
+    const std::function<void()>& on_stop_complete_user_callback) {
+  LOG(INFO) << "Stopping legacy HAL";
+  on_stop_complete_internal_callback = [&](wifi_handle handle) {
+    CHECK_EQ(global_handle_, handle) << "Handle mismatch";
+    on_stop_complete_user_callback();
+    global_handle_ = nullptr;
+    wlan_interface_handle_ = nullptr;
+    on_stop_complete_internal_callback = nullptr;
+  };
+  awaiting_event_loop_termination_ = true;
+  global_func_table_.wifi_cleanup(global_handle_, onStopComplete);
+  LOG(VERBOSE) << "Legacy HAL stop initiated";
+  return WIFI_SUCCESS;
+}
+
+wifi_error WifiLegacyHal::retrieveWlanInterfaceHandle() {
+  const std::string& ifname_to_find = getWlanInterfaceName();
+
+  wifi_interface_handle* iface_handles = nullptr;
+  int num_iface_handles = 0;
+  wifi_error status = global_func_table_.wifi_get_ifaces(
+      global_handle_, &num_iface_handles, &iface_handles);
+  if (status != WIFI_SUCCESS) {
+    LOG(ERROR) << "Failed to enumerate interface handles: "
+               << LegacyErrorToString(status);
+    return status;
+  }
+  for (int i = 0; i < num_iface_handles; ++i) {
+    std::array<char, IFNAMSIZ> current_ifname;
+    current_ifname.fill(0);
+    status = global_func_table_.wifi_get_iface_name(
+        iface_handles[i], current_ifname.data(), current_ifname.size());
+    if (status != WIFI_SUCCESS) {
+      LOG(WARNING) << "Failed to get interface handle name: "
+                   << LegacyErrorToString(status);
+      continue;
+    }
+    if (ifname_to_find == current_ifname.data()) {
+      wlan_interface_handle_ = iface_handles[i];
+      return WIFI_SUCCESS;
+    }
+  }
+  return WIFI_ERROR_UNKNOWN;
+}
+
+void WifiLegacyHal::runEventLoop() {
+  LOG(VERBOSE) << "Starting legacy HAL event loop";
+  global_func_table_.wifi_event_loop(global_handle_);
+  if (!awaiting_event_loop_termination_) {
+    LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping";
+  }
+  LOG(VERBOSE) << "Legacy HAL event loop terminated";
+  awaiting_event_loop_termination_ = false;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.0/default/wifi_legacy_hal.h b/wifi/1.0/default/wifi_legacy_hal.h
new file mode 100644
index 0000000..1af9f1a
--- /dev/null
+++ b/wifi/1.0/default/wifi_legacy_hal.h
@@ -0,0 +1,67 @@
+/*
+ * 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 WIFI_LEGACY_WIFI_HAL_H_
+#define WIFI_LEGACY_WIFI_HAL_H_
+
+#include <functional>
+#include <thread>
+
+#include <hardware_legacy/wifi_hal.h>
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_0 {
+namespace implementation {
+
+/**
+ * Class that encapsulates all legacy HAL interactions.
+ * This class manages the lifetime of the event loop thread used by legacy HAL.
+ */
+class WifiLegacyHal {
+ public:
+  WifiLegacyHal();
+  // Initialize the legacy HAL and start the event looper thread.
+  wifi_error start();
+  // Deinitialize the legacy HAL and stop the event looper thread.
+  wifi_error stop(const std::function<void()>& on_complete_callback);
+
+ private:
+  // Retrieve the interface handle to be used for the "wlan" interface.
+  wifi_error retrieveWlanInterfaceHandle();
+  // Run the legacy HAL event loop thread.
+  void runEventLoop();
+
+  // Event loop thread used by legacy HAL.
+  std::thread event_loop_thread_;
+  // Global function table of legacy HAL.
+  wifi_hal_fn global_func_table_;
+  // Opaque handle to be used for all global operations.
+  wifi_handle global_handle_;
+  // Opaque handle to be used for all wlan0 interface specific operations.
+  wifi_interface_handle wlan_interface_handle_;
+  // Flag to indicate if we have initiated the cleanup of legacy HAL.
+  bool awaiting_event_loop_termination_;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_LEGACY_WIFI_HAL_H_