wifi: Restructure wifi legacy HAL implementation am: aabe575536 am: e9301b4c57 am: 79ddd9f48b

am: fcf91b089f

Change-Id: I1e372b2c5bd94ec02d31e281c92107729cf66981
This commit is contained in:
Roshan Pius 2016-10-05 23:49:16 +00:00 committed by android-build-merger
commit 289a0f0462
10 changed files with 281 additions and 314 deletions

View file

@ -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 \

View file

@ -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;

View file

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

View file

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

View file

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

View file

@ -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 wifi {
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);
void Invalidate();
WifiChip(std::weak_ptr<WifiLegacyHal> legacy_hal);
// Invalidate this instance once the HAL is stopped.
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);

View file

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

View file

@ -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_

View file

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

View file

@ -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_