Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aabe5755 authored by Roshan Pius's avatar Roshan Pius
Browse files

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
parent 79a9975d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ LOCAL_SRC_FILES := \
    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 \
+4 −3
Original line number Diff line number Diff line
@@ -55,13 +55,14 @@ int main(int /*argc*/, char** argv) {

  // 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;
+36 −104
Original line number Diff line number Diff line
@@ -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,129 +38,74 @@ Return<void> Wifi::registerEventCallback(
}

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) {
    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();
  } else if (run_state_ == RunState::STOPPING) {
    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();
  });
  LOG(INFO) << "Stopping HAL";
  run_state_ = RunState::STOPPING;
  const auto on_complete_callback_ = [&]() {
    if (chip_.get()) {
      chip_->invalidate();
    }

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_) {
    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();
}

Return<void> Wifi::getChip(getChip_cb cb) {
+11 −27
Original line number Diff line number Diff line
@@ -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 wifi {
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);

  /**
   * 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();
  enum class RunState { STOPPED, STARTED, STOPPING };

  // 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);
};

+10 −42
Original line number Diff line number Diff line
@@ -26,18 +26,17 @@ namespace wifi {
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::registerEventCallback(
}

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::getAvailableModes(getAvailableModes_cb cb) {
}

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();
}

Loading