wifi: Move legacy HAL implementation

Changes in the CL:
1. Move the legacy HAL implementation from
"frameworks/opt/net/wifi/wifi_hal_legacy" to
"hardware/interfaces/wifi/1.0/default".
2. Renamed the .rc file and the module name in makefile to
conform to the HIDL style guide.

Files renamed from:
wifi_hal_service.cpp/h -> wifi.cpp/h
wifi_chip_service.cpp/h -> wifi_chip.cpp/h
main.cpp -> service

Bug: 31821133
Test: mmma -j32 hardware/interfaces/wifi/1.0/default
Change-Id: I5e65e2fdb5596346bde6963588031dcea42d633a
diff --git a/wifi/1.0/default/Android.mk b/wifi/1.0/default/Android.mk
new file mode 100644
index 0000000..6180efd
--- /dev/null
+++ b/wifi/1.0/default/Android.mk
@@ -0,0 +1,55 @@
+# 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.
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.wifi@1.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_CPPFLAGS := -std=c++11 -Wall -Wno-unused-parameter -Werror -Wextra
+LOCAL_SRC_FILES := \
+    failure_reason_util.cpp \
+    wifi_chip.cpp \
+    wifi.cpp \
+    wifi_hal_state.cpp
+LOCAL_SHARED_LIBRARIES := \
+    android.hardware.wifi@1.0 \
+    libbase \
+    libcutils \
+    libhidl \
+    libhwbinder \
+    liblog \
+    libnl \
+    libutils
+LOCAL_WHOLE_STATIC_LIBRARIES := $(LIB_WIFI_HAL)
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.wifi@1.0-service
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_CPPFLAGS := -std=c++11 -Wall -Wno-unused-parameter -Werror -Wextra
+LOCAL_SRC_FILES := \
+    service.cpp
+LOCAL_SHARED_LIBRARIES := \
+    android.hardware.wifi@1.0 \
+    android.hardware.wifi@1.0-impl \
+    libbase \
+    libcutils \
+    libhidl \
+    libhwbinder \
+    liblog \
+    libnl \
+    libutils
+LOCAL_WHOLE_STATIC_LIBRARIES := $(LIB_WIFI_HAL)
+LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc
+include $(BUILD_EXECUTABLE)
diff --git a/wifi/1.0/default/android.hardware.wifi@1.0-service.rc b/wifi/1.0/default/android.hardware.wifi@1.0-service.rc
new file mode 100644
index 0000000..9d09347
--- /dev/null
+++ b/wifi/1.0/default/android.hardware.wifi@1.0-service.rc
@@ -0,0 +1,4 @@
+service wifi_hal_legacy /system/bin/hw/android.hardware.wifi@1.0-service
+    class hal
+    user wifi
+    group wifi
diff --git a/wifi/1.0/default/failure_reason_util.cpp b/wifi/1.0/default/failure_reason_util.cpp
new file mode 100644
index 0000000..7fd2269
--- /dev/null
+++ b/wifi/1.0/default/failure_reason_util.cpp
@@ -0,0 +1,94 @@
+/*
+ * 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 "failure_reason_util.h"
+
+using ::android::hardware::wifi::V1_0::CommandFailureReason;
+
+namespace android {
+namespace hardware {
+namespace wifi {
+
+std::string LegacyErrorToString(wifi_error error) {
+  switch(error) {
+    case WIFI_SUCCESS:
+      return "SUCCESS";
+    case WIFI_ERROR_UNINITIALIZED:
+      return "UNINITIALIZED";
+    case WIFI_ERROR_NOT_AVAILABLE:
+      return "NOT_AVAILABLE";
+    case WIFI_ERROR_NOT_SUPPORTED:
+      return "NOT_SUPPORTED";
+    case WIFI_ERROR_INVALID_ARGS:
+      return "INVALID_ARGS";
+    case WIFI_ERROR_INVALID_REQUEST_ID:
+      return "INVALID_REQUEST_ID";
+    case WIFI_ERROR_TIMED_OUT:
+      return "TIMED_OUT";
+    case WIFI_ERROR_TOO_MANY_REQUESTS:
+      return "TOO_MANY_REQUESTS";
+    case WIFI_ERROR_OUT_OF_MEMORY:
+      return "OUT_OF_MEMORY";
+    case WIFI_ERROR_UNKNOWN:
+    default:
+      return "UNKNOWN";
+  }
+}
+
+V1_0::FailureReason CreateFailureReason(
+    CommandFailureReason reason, const std::string& description) {
+  V1_0::FailureReason result;
+  result.reason = reason;
+  result.description = description.data();
+  return result;
+}
+
+V1_0::FailureReason CreateFailureReasonLegacyError(
+    wifi_error error, const std::string& desc) {
+  switch(error) {
+    case WIFI_ERROR_UNINITIALIZED:
+    case WIFI_ERROR_NOT_AVAILABLE:
+      return CreateFailureReason(CommandFailureReason::NOT_AVAILABLE, desc);
+
+    case WIFI_ERROR_NOT_SUPPORTED:
+      return CreateFailureReason(CommandFailureReason::NOT_SUPPORTED, desc);
+
+    case WIFI_ERROR_INVALID_ARGS:
+    case WIFI_ERROR_INVALID_REQUEST_ID:
+      return CreateFailureReason(CommandFailureReason::INVALID_ARGS, desc);
+
+    case WIFI_ERROR_TIMED_OUT:
+      return CreateFailureReason(
+          CommandFailureReason::UNKNOWN, desc + ", timed out");
+
+    case WIFI_ERROR_TOO_MANY_REQUESTS:
+      return CreateFailureReason(
+          CommandFailureReason::UNKNOWN, desc + ", too many requests");
+
+    case WIFI_ERROR_OUT_OF_MEMORY:
+      return CreateFailureReason(
+          CommandFailureReason::UNKNOWN, desc + ", out of memory");
+
+    case WIFI_ERROR_NONE:
+    case WIFI_ERROR_UNKNOWN:
+    default:
+      return CreateFailureReason(CommandFailureReason::UNKNOWN, "unknown");
+  }
+}
+
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.0/default/failure_reason_util.h b/wifi/1.0/default/failure_reason_util.h
new file mode 100644
index 0000000..d731700
--- /dev/null
+++ b/wifi/1.0/default/failure_reason_util.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 FAILURE_REASON_UTIL_H_
+#define FAILURE_REASON_UTIL_H_
+
+#include <android/hardware/wifi/1.0/IWifi.h>
+#include <hardware_legacy/wifi_hal.h>
+
+namespace android {
+namespace hardware {
+namespace wifi {
+
+std::string LegacyErrorToString(wifi_error error);
+
+V1_0::FailureReason CreateFailureReason(
+    V1_0::CommandFailureReason reason, const std::string& description);
+V1_0::FailureReason CreateFailureReasonLegacyError(
+    wifi_error error, const std::string& description);
+
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // FAILURE_REASON_UTIL_H_
diff --git a/wifi/1.0/default/service.cpp b/wifi/1.0/default/service.cpp
new file mode 100644
index 0000000..a96584b
--- /dev/null
+++ b/wifi/1.0/default/service.cpp
@@ -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.
+ */
+
+#include <android-base/logging.h>
+#include <hidl/IServiceManager.h>
+#include <hwbinder/IPCThreadState.h>
+#include <hwbinder/ProcessState.h>
+#include <utils/Looper.h>
+#include <utils/StrongPointer.h>
+
+#include "wifi.h"
+
+using android::hardware::hidl_version;
+using android::hardware::IPCThreadState;
+using android::hardware::ProcessState;
+using android::Looper;
+
+namespace {
+int OnBinderReadReady(int /*fd*/, int /*events*/, void* /*data*/) {
+  IPCThreadState::self()->handlePolledCommands();
+  return 1;  // continue receiving events
+}
+}
+
+int main(int /*argc*/, char** argv) {
+  android::base::InitLogging(
+      argv, android::base::LogdLogger(android::base::SYSTEM));
+  LOG(INFO) << "wifi_hal_legacy is starting up...";
+
+  // Setup binder
+  int binder_fd = -1;
+  ProcessState::self()->setThreadPoolMaxThreadCount(0);
+  CHECK_EQ(IPCThreadState::self()->setupPolling(&binder_fd),
+           android::NO_ERROR) << "Failed to initialize binder polling";
+  CHECK_GE(binder_fd, 0) << "Invalid binder FD: " << binder_fd;
+
+  // Setup looper
+  android::sp<Looper> looper = Looper::prepare(0 /* no options */);
+  CHECK(looper->addFd(
+      binder_fd, 0, Looper::EVENT_INPUT, OnBinderReadReady, nullptr))
+      << "Failed to watch binder FD";
+
+  // Setup hwbinder service
+  android::sp<android::hardware::wifi::Wifi> service =
+      new android::hardware::wifi::Wifi(looper);
+  CHECK_EQ(service->registerAsService("wifi"),
+           android::NO_ERROR) << "Failed to register wifi HAL";
+
+  // Loop
+  while (looper->pollAll(-1) != Looper::POLL_ERROR);
+
+  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
new file mode 100644
index 0000000..0e10bfb
--- /dev/null
+++ b/wifi/1.0/default/wifi.cpp
@@ -0,0 +1,187 @@
+/*
+ * 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.h"
+
+#include <android-base/logging.h>
+#include <cutils/properties.h>
+
+#include "failure_reason_util.h"
+#include "wifi_chip.h"
+
+using ::android::hardware::wifi::V1_0::CommandFailureReason;
+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 {
+
+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";
+}
+
+Return<void> Wifi::registerEventCallback(
+    const sp<V1_0::IWifiEventCallback>& callback) {
+  // TODO(b/31632518): remove the callback when the client is destroyed
+  callbacks_.insert(callback);
+  return Void();
+}
+
+Return<bool> Wifi::isStarted() {
+  return state_.run_state_ != RunState::STOPPED;
+}
+
+Return<void> Wifi::start() {
+  if (state_.run_state_ == RunState::STARTED) {
+    for (auto& callback : callbacks_) {
+      callback->onStart();
+    }
+    return Void();
+  } else if (state_.run_state_ == RunState::STOPPING) {
+    for (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_);
+  if (status != WIFI_SUCCESS) {
+    LOG(ERROR) << "Failed to initialize Wifi HAL";
+    for (auto& callback : callbacks_) {
+      callback->onStartFailure(CreateFailureReasonLegacyError(
+          status, "Failed to initialize 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_) {
+    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_) {
+      callback->onStop();
+    }
+    return Void();
+  } else if (state_.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();
+  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();
+}
+
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.0/default/wifi.h b/wifi/1.0/default/wifi.h
new file mode 100644
index 0000000..92712fd
--- /dev/null
+++ b/wifi/1.0/default/wifi.h
@@ -0,0 +1,83 @@
+/*
+ * 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_H_
+#define WIFI_H_
+
+#include <functional>
+#include <set>
+#include <thread>
+
+#include <android/hardware/wifi/1.0/IWifi.h>
+#include <android-base/macros.h>
+#include <hardware_legacy/wifi_hal.h>
+#include <utils/Looper.h>
+
+#include "wifi_hal_state.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+
+class WifiChip;
+
+class Wifi : public V1_0::IWifi {
+ public:
+  Wifi(sp<Looper>& looper);
+
+  Return<void> registerEventCallback(
+      const sp<V1_0::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);
+
+  /**
+   * 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();
+
+  std::set<sp<V1_0::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);
+};
+
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_H_
diff --git a/wifi/1.0/default/wifi_chip.cpp b/wifi/1.0/default/wifi_chip.cpp
new file mode 100644
index 0000000..e794f53
--- /dev/null
+++ b/wifi/1.0/default/wifi_chip.cpp
@@ -0,0 +1,116 @@
+/*
+ * 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_chip.h"
+
+#include <android-base/logging.h>
+
+#include "failure_reason_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+
+WifiChip::WifiChip(
+    WifiHalState* hal_state, wifi_interface_handle interface_handle)
+    : hal_state_(hal_state), interface_handle_(interface_handle) {}
+
+void WifiChip::Invalidate() {
+  hal_state_ = nullptr;
+  callbacks_.clear();
+}
+
+Return<void> WifiChip::registerEventCallback(
+    const sp<V1_0::IWifiChipEventCallback>& callback) {
+  if (!hal_state_) return Void();
+  // TODO(b/31632518): remove the callback when the client is destroyed
+  callbacks_.insert(callback);
+  return Void();
+}
+
+Return<void> WifiChip::getAvailableModes(getAvailableModes_cb cb) {
+  if (!hal_state_) {
+    cb(hidl_vec<ChipMode>());
+    return Void();
+  } else {
+    // TODO add implementation
+    return Void();
+  }
+}
+
+Return<void> WifiChip::configureChip(uint32_t /*mode_id*/) {
+  if (!hal_state_) return Void();
+  // TODO add implementation
+  return Void();
+}
+
+Return<uint32_t> WifiChip::getMode() {
+  if (!hal_state_) return 0;
+  // TODO add implementation
+  return 0;
+}
+
+Return<void> WifiChip::requestChipDebugInfo() {
+  if (!hal_state_) return Void();
+
+  V1_0::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);
+  }
+  return Void();
+}
+
+Return<void> WifiChip::requestDriverDebugDump() {
+  // TODO implement
+  return Void();
+}
+
+Return<void> WifiChip::requestFirmwareDebugDump() {
+  // TODO implement
+  return Void();
+}
+
+
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.0/default/wifi_chip.h b/wifi/1.0/default/wifi_chip.h
new file mode 100644
index 0000000..583c151
--- /dev/null
+++ b/wifi/1.0/default/wifi_chip.h
@@ -0,0 +1,66 @@
+/*
+ * 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_CHIP_H_
+#define WIFI_CHIP_H_
+
+#include <set>
+
+#include <android/hardware/wifi/1.0/IWifiChip.h>
+#include <android-base/macros.h>
+#include <hardware_legacy/wifi_hal.h>
+
+#include "wifi_hal_state.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+
+class WifiChip : public V1_0::IWifiChip {
+ public:
+  WifiChip(
+      WifiHalState* hal_state, wifi_interface_handle interface_handle);
+
+  void Invalidate();
+
+  Return<void> registerEventCallback(
+      const sp<V1_0::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::set<sp<V1_0::IWifiChipEventCallback>> callbacks_;
+
+  DISALLOW_COPY_AND_ASSIGN(WifiChip);
+};
+
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_CHIP_H_
diff --git a/wifi/1.0/default/wifi_hal_state.cpp b/wifi/1.0/default/wifi_hal_state.cpp
new file mode 100644
index 0000000..11387d8
--- /dev/null
+++ b/wifi/1.0/default/wifi_hal_state.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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 {
+
+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 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
new file mode 100644
index 0000000..6b9fc53
--- /dev/null
+++ b/wifi/1.0/default/wifi_hal_state.h
@@ -0,0 +1,62 @@
+/*
+ * 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 {
+
+/**
+ * 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 wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_HAL_LEGACY_WIFI_HAL_STATE_H_