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/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