From 3c4e8a358c96cb4781fbfeaa2718695260bb39ba Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Mon, 3 Oct 2016 14:53:58 -0700 Subject: [PATCH 1/8] 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 --- wifi/1.0/default/Android.mk | 55 ++++++ .../android.hardware.wifi@1.0-service.rc | 4 + wifi/1.0/default/failure_reason_util.cpp | 94 +++++++++ wifi/1.0/default/failure_reason_util.h | 38 ++++ wifi/1.0/default/service.cpp | 67 +++++++ wifi/1.0/default/wifi.cpp | 187 ++++++++++++++++++ wifi/1.0/default/wifi.h | 83 ++++++++ wifi/1.0/default/wifi_chip.cpp | 116 +++++++++++ wifi/1.0/default/wifi_chip.h | 66 +++++++ wifi/1.0/default/wifi_hal_state.cpp | 58 ++++++ wifi/1.0/default/wifi_hal_state.h | 62 ++++++ 11 files changed, 830 insertions(+) create mode 100644 wifi/1.0/default/Android.mk create mode 100644 wifi/1.0/default/android.hardware.wifi@1.0-service.rc create mode 100644 wifi/1.0/default/failure_reason_util.cpp create mode 100644 wifi/1.0/default/failure_reason_util.h create mode 100644 wifi/1.0/default/service.cpp create mode 100644 wifi/1.0/default/wifi.cpp create mode 100644 wifi/1.0/default/wifi.h create mode 100644 wifi/1.0/default/wifi_chip.cpp create mode 100644 wifi/1.0/default/wifi_chip.h create mode 100644 wifi/1.0/default/wifi_hal_state.cpp create mode 100644 wifi/1.0/default/wifi_hal_state.h diff --git a/wifi/1.0/default/Android.mk b/wifi/1.0/default/Android.mk new file mode 100644 index 0000000000..6180efdf9b --- /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 0000000000..9d09347d84 --- /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 0000000000..7fd226978a --- /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 0000000000..d731700347 --- /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 +#include + +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 0000000000..a96584b701 --- /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 +#include +#include +#include +#include +#include + +#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::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 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 0000000000..0e10bfbcff --- /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 +#include + +#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) : state_(looper) { + CHECK_EQ(init_wifi_vendor_hal_func_table(&state_.func_table_), WIFI_SUCCESS) + << "Failed to initialize hal func table"; +} + +Return Wifi::registerEventCallback( + const sp& callback) { + // TODO(b/31632518): remove the callback when the client is destroyed + callbacks_.insert(callback); + return Void(); +} + +Return Wifi::isStarted() { + return state_.run_state_ != RunState::STOPPED; +} + +Return 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 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 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 0000000000..92712fd961 --- /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 +#include +#include + +#include +#include +#include +#include + +#include "wifi_hal_state.h" + +namespace android { +namespace hardware { +namespace wifi { + +class WifiChip; + +class Wifi : public V1_0::IWifi { + public: + Wifi(sp& looper); + + Return registerEventCallback( + const sp& callback) override; + + Return isStarted() override; + Return start() override; + Return stop() override; + + Return 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> callbacks_; + sp 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 0000000000..e794f538a0 --- /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 + +#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 WifiChip::registerEventCallback( + const sp& callback) { + if (!hal_state_) return Void(); + // TODO(b/31632518): remove the callback when the client is destroyed + callbacks_.insert(callback); + return Void(); +} + +Return WifiChip::getAvailableModes(getAvailableModes_cb cb) { + if (!hal_state_) { + cb(hidl_vec()); + return Void(); + } else { + // TODO add implementation + return Void(); + } +} + +Return WifiChip::configureChip(uint32_t /*mode_id*/) { + if (!hal_state_) return Void(); + // TODO add implementation + return Void(); +} + +Return WifiChip::getMode() { + if (!hal_state_) return 0; + // TODO add implementation + return 0; +} + +Return WifiChip::requestChipDebugInfo() { + if (!hal_state_) return Void(); + + V1_0::IWifiChipEventCallback::ChipDebugInfo result; + result.driverDescription = ""; + result.firmwareDescription = ""; + 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 WifiChip::requestDriverDebugDump() { + // TODO implement + return Void(); +} + +Return 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 0000000000..583c15185e --- /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 + +#include +#include +#include + +#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 registerEventCallback( + const sp& callback) override; + + Return getAvailableModes(getAvailableModes_cb cb) override; + + Return configureChip(uint32_t mode_id) override; + + Return getMode() override; + + Return requestChipDebugInfo() override; + + Return requestDriverDebugDump() override; + + Return requestFirmwareDebugDump() override; + + private: + WifiHalState* hal_state_; + wifi_interface_handle interface_handle_; + std::set> 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 0000000000..11387d83d2 --- /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 +#include +#include + +namespace { +class FunctionMessageHandler : public android::MessageHandler { + public: + explicit FunctionMessageHandler(const std::function& callback) + : callback_(callback) { + } + + ~FunctionMessageHandler() override = default; + + virtual void handleMessage(const android::Message& /*message*/) { + callback_(); + } + + private: + const std::function callback_; + + DISALLOW_COPY_AND_ASSIGN(FunctionMessageHandler); +}; +} + +namespace android { +namespace hardware { +namespace wifi { + +WifiHalState::WifiHalState(sp& looper) + : run_state_(RunState::STOPPED), looper_(looper) {} + +void WifiHalState::PostTask(const std::function& callback) { + sp 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 0000000000..6b9fc53acd --- /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 + +#include +#include +#include + +namespace android { +namespace hardware { +namespace wifi { + +/** + * Class that stores common state and functionality shared between HAL services. + */ +class WifiHalState { + public: + WifiHalState(sp& looper); + + /** Post a task to be executed on the main thread */ + void PostTask(const std::function& 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_; + + DISALLOW_COPY_AND_ASSIGN(WifiHalState); +}; + +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_HAL_LEGACY_WIFI_HAL_STATE_H_ From 79a9975d07ec1fc583f4f281469bf3c05c909034 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 4 Oct 2016 13:03:58 -0700 Subject: [PATCH 2/8] wifi: Change namespace Move the implementation to "android::hardware::wifi:V1_0::implementation" namespace. This is following the style guidelines in NFC HIDL implementation(go/aog/279421). While there, Run checkstyle to correct formatting issues. Bug:31936700 Test: mmma -j32 hardware/interfaces/wifi/1.0/default Change-Id: I5600a60a0041b3318ed9289823ec335a8ed8a83d --- wifi/1.0/default/failure_reason_util.cpp | 32 +++++++++++++----------- wifi/1.0/default/failure_reason_util.h | 12 ++++++--- wifi/1.0/default/service.cpp | 19 +++++++------- wifi/1.0/default/wifi.cpp | 27 ++++++++++---------- wifi/1.0/default/wifi.h | 15 ++++++----- wifi/1.0/default/wifi_chip.cpp | 25 +++++++++++------- wifi/1.0/default/wifi_chip.h | 15 ++++++----- wifi/1.0/default/wifi_hal_state.cpp | 10 +++++--- wifi/1.0/default/wifi_hal_state.h | 10 ++++---- 9 files changed, 94 insertions(+), 71 deletions(-) diff --git a/wifi/1.0/default/failure_reason_util.cpp b/wifi/1.0/default/failure_reason_util.cpp index 7fd226978a..f703ebe2c2 100644 --- a/wifi/1.0/default/failure_reason_util.cpp +++ b/wifi/1.0/default/failure_reason_util.cpp @@ -16,14 +16,14 @@ #include "failure_reason_util.h" -using ::android::hardware::wifi::V1_0::CommandFailureReason; - namespace android { namespace hardware { namespace wifi { +namespace V1_0 { +namespace implementation { std::string LegacyErrorToString(wifi_error error) { - switch(error) { + switch (error) { case WIFI_SUCCESS: return "SUCCESS"; case WIFI_ERROR_UNINITIALIZED: @@ -48,17 +48,17 @@ std::string LegacyErrorToString(wifi_error error) { } } -V1_0::FailureReason CreateFailureReason( - CommandFailureReason reason, const std::string& description) { - V1_0::FailureReason result; +FailureReason CreateFailureReason(CommandFailureReason reason, + const std::string& description) { + FailureReason result; result.reason = reason; result.description = description.data(); return result; } -V1_0::FailureReason CreateFailureReasonLegacyError( - wifi_error error, const std::string& desc) { - switch(error) { +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); @@ -71,16 +71,16 @@ V1_0::FailureReason CreateFailureReasonLegacyError( return CreateFailureReason(CommandFailureReason::INVALID_ARGS, desc); case WIFI_ERROR_TIMED_OUT: - return CreateFailureReason( - CommandFailureReason::UNKNOWN, desc + ", timed out"); + return CreateFailureReason(CommandFailureReason::UNKNOWN, + desc + ", timed out"); case WIFI_ERROR_TOO_MANY_REQUESTS: - return CreateFailureReason( - CommandFailureReason::UNKNOWN, desc + ", 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"); + return CreateFailureReason(CommandFailureReason::UNKNOWN, + desc + ", out of memory"); case WIFI_ERROR_NONE: case WIFI_ERROR_UNKNOWN: @@ -89,6 +89,8 @@ V1_0::FailureReason CreateFailureReasonLegacyError( } } +} // namespace implementation +} // namespace V1_0 } // 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 index d731700347..7d51bbf2fe 100644 --- a/wifi/1.0/default/failure_reason_util.h +++ b/wifi/1.0/default/failure_reason_util.h @@ -23,14 +23,18 @@ namespace android { namespace hardware { namespace wifi { +namespace V1_0 { +namespace implementation { 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); +FailureReason CreateFailureReason(CommandFailureReason reason, + const std::string& description); +FailureReason CreateFailureReasonLegacyError(wifi_error error, + const std::string& description); +} // namespace implementation +} // namespace V1_0 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.0/default/service.cpp b/wifi/1.0/default/service.cpp index a96584b701..07e6c81e0d 100644 --- a/wifi/1.0/default/service.cpp +++ b/wifi/1.0/default/service.cpp @@ -36,15 +36,15 @@ int OnBinderReadReady(int /*fd*/, int /*events*/, void* /*data*/) { } int main(int /*argc*/, char** argv) { - android::base::InitLogging( - argv, android::base::LogdLogger(android::base::SYSTEM)); + 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_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 @@ -54,13 +54,14 @@ int main(int /*argc*/, char** argv) { << "Failed to watch binder FD"; // Setup hwbinder service - android::sp service = - new android::hardware::wifi::Wifi(looper); - CHECK_EQ(service->registerAsService("wifi"), - android::NO_ERROR) << "Failed to register wifi HAL"; + android::sp service = + new android::hardware::wifi::V1_0::implementation::Wifi(looper); + 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) + ; 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 0e10bfbcff..aa0fc5b65f 100644 --- a/wifi/1.0/default/wifi.cpp +++ b/wifi/1.0/default/wifi.cpp @@ -22,7 +22,6 @@ #include "failure_reason_util.h" #include "wifi_chip.h" -using ::android::hardware::wifi::V1_0::CommandFailureReason; using RunState = ::android::hardware::wifi::WifiHalState::RunState; namespace { @@ -36,6 +35,8 @@ std::string GetWlanInterfaceName() { namespace android { namespace hardware { namespace wifi { +namespace V1_0 { +namespace implementation { Wifi::Wifi(sp& looper) : state_(looper) { CHECK_EQ(init_wifi_vendor_hal_func_table(&state_.func_table_), WIFI_SUCCESS) @@ -43,7 +44,7 @@ Wifi::Wifi(sp& looper) : state_(looper) { } Return Wifi::registerEventCallback( - const sp& callback) { + const sp& callback) { // TODO(b/31632518): remove the callback when the client is destroyed callbacks_.insert(callback); return Void(); @@ -72,8 +73,8 @@ Return Wifi::start() { if (status != WIFI_SUCCESS) { LOG(ERROR) << "Failed to initialize Wifi HAL"; for (auto& callback : callbacks_) { - callback->onStartFailure(CreateFailureReasonLegacyError( - status, "Failed to initialize HAL")); + callback->onStartFailure( + CreateFailureReasonLegacyError(status, "Failed to initialize HAL")); } return Void(); } @@ -95,8 +96,7 @@ Return Wifi::start() { return Void(); } -wifi_interface_handle Wifi::FindInterfaceHandle( - const std::string& ifname) { +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( @@ -124,7 +124,6 @@ wifi_interface_handle Wifi::FindInterfaceHandle( return kInterfaceNotFoundHandle; } - void NoopHalCleanupHandler(wifi_handle) {} Return Wifi::stop() { @@ -142,7 +141,8 @@ Return Wifi::stop() { awaiting_hal_event_loop_termination_ = true; state_.run_state_ = RunState::STOPPING; - if (chip_.get()) chip_->Invalidate(); + if (chip_.get()) + chip_->Invalidate(); chip_.clear(); state_.func_table_.wifi_cleanup(state_.hal_handle_, NoopHalCleanupHandler); @@ -160,10 +160,10 @@ void Wifi::DoHalEventLoop() { } LOG(VERBOSE) << "HAL Event loop terminated"; event_loop_thread_.detach(); - state_.PostTask([this](){ - awaiting_hal_event_loop_termination_ = false; - FinishHalCleanup(); - }); + state_.PostTask([this]() { + awaiting_hal_event_loop_termination_ = false; + FinishHalCleanup(); + }); } void Wifi::FinishHalCleanup() { @@ -176,12 +176,13 @@ void Wifi::FinishHalCleanup() { } } - Return Wifi::getChip(getChip_cb cb) { cb(chip_); return Void(); } +} // namespace implementation +} // namespace V1_0 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.0/default/wifi.h b/wifi/1.0/default/wifi.h index 92712fd961..01227418a1 100644 --- a/wifi/1.0/default/wifi.h +++ b/wifi/1.0/default/wifi.h @@ -21,25 +21,26 @@ #include #include -#include #include +#include #include #include #include "wifi_hal_state.h" +#include "wifi_chip.h" namespace android { namespace hardware { namespace wifi { +namespace V1_0 { +namespace implementation { -class WifiChip; - -class Wifi : public V1_0::IWifi { +class Wifi : public IWifi { public: Wifi(sp& looper); Return registerEventCallback( - const sp& callback) override; + const sp& callback) override; Return isStarted() override; Return start() override; @@ -63,7 +64,7 @@ class Wifi : public V1_0::IWifi { */ void DoHalEventLoop(); - std::set> callbacks_; + std::set> callbacks_; sp chip_; WifiHalState state_; @@ -76,6 +77,8 @@ class Wifi : public V1_0::IWifi { DISALLOW_COPY_AND_ASSIGN(Wifi); }; +} // namespace implementation +} // namespace V1_0 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.0/default/wifi_chip.cpp b/wifi/1.0/default/wifi_chip.cpp index e794f538a0..42118b75d2 100644 --- a/wifi/1.0/default/wifi_chip.cpp +++ b/wifi/1.0/default/wifi_chip.cpp @@ -23,9 +23,11 @@ namespace android { namespace hardware { namespace wifi { +namespace V1_0 { +namespace implementation { -WifiChip::WifiChip( - WifiHalState* hal_state, wifi_interface_handle interface_handle) +WifiChip::WifiChip(WifiHalState* hal_state, + wifi_interface_handle interface_handle) : hal_state_(hal_state), interface_handle_(interface_handle) {} void WifiChip::Invalidate() { @@ -34,8 +36,9 @@ void WifiChip::Invalidate() { } Return WifiChip::registerEventCallback( - const sp& callback) { - if (!hal_state_) return Void(); + const sp& callback) { + if (!hal_state_) + return Void(); // TODO(b/31632518): remove the callback when the client is destroyed callbacks_.insert(callback); return Void(); @@ -52,21 +55,24 @@ Return WifiChip::getAvailableModes(getAvailableModes_cb cb) { } Return WifiChip::configureChip(uint32_t /*mode_id*/) { - if (!hal_state_) return Void(); + if (!hal_state_) + return Void(); // TODO add implementation return Void(); } Return WifiChip::getMode() { - if (!hal_state_) return 0; + if (!hal_state_) + return 0; // TODO add implementation return 0; } Return WifiChip::requestChipDebugInfo() { - if (!hal_state_) return Void(); + if (!hal_state_) + return Void(); - V1_0::IWifiChipEventCallback::ChipDebugInfo result; + IWifiChipEventCallback::ChipDebugInfo result; result.driverDescription = ""; result.firmwareDescription = ""; char buffer[256]; @@ -110,7 +116,8 @@ Return WifiChip::requestFirmwareDebugDump() { return Void(); } - +} // namespace implementation +} // namespace V1_0 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.0/default/wifi_chip.h b/wifi/1.0/default/wifi_chip.h index 583c15185e..d776644581 100644 --- a/wifi/1.0/default/wifi_chip.h +++ b/wifi/1.0/default/wifi_chip.h @@ -19,8 +19,8 @@ #include -#include #include +#include #include #include "wifi_hal_state.h" @@ -28,16 +28,17 @@ namespace android { namespace hardware { namespace wifi { +namespace V1_0 { +namespace implementation { -class WifiChip : public V1_0::IWifiChip { +class WifiChip : public IWifiChip { public: - WifiChip( - WifiHalState* hal_state, wifi_interface_handle interface_handle); + WifiChip(WifiHalState* hal_state, wifi_interface_handle interface_handle); void Invalidate(); Return registerEventCallback( - const sp& callback) override; + const sp& callback) override; Return getAvailableModes(getAvailableModes_cb cb) override; @@ -54,11 +55,13 @@ class WifiChip : public V1_0::IWifiChip { private: WifiHalState* hal_state_; wifi_interface_handle interface_handle_; - std::set> callbacks_; + std::set> callbacks_; DISALLOW_COPY_AND_ASSIGN(WifiChip); }; +} // namespace implementation +} // namespace V1_0 } // namespace wifi } // namespace hardware } // namespace android diff --git a/wifi/1.0/default/wifi_hal_state.cpp b/wifi/1.0/default/wifi_hal_state.cpp index 11387d83d2..148368996a 100644 --- a/wifi/1.0/default/wifi_hal_state.cpp +++ b/wifi/1.0/default/wifi_hal_state.cpp @@ -24,8 +24,7 @@ namespace { class FunctionMessageHandler : public android::MessageHandler { public: explicit FunctionMessageHandler(const std::function& callback) - : callback_(callback) { - } + : callback_(callback) {} ~FunctionMessageHandler() override = default; @@ -43,16 +42,19 @@ class FunctionMessageHandler : public android::MessageHandler { namespace android { namespace hardware { namespace wifi { +namespace V1_0 { +namespace implementation { WifiHalState::WifiHalState(sp& looper) : run_state_(RunState::STOPPED), looper_(looper) {} void WifiHalState::PostTask(const std::function& callback) { - sp message_handler = - new FunctionMessageHandler(callback); + sp 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 index 6b9fc53acd..40e39ec424 100644 --- a/wifi/1.0/default/wifi_hal_state.h +++ b/wifi/1.0/default/wifi_hal_state.h @@ -26,6 +26,8 @@ namespace android { namespace hardware { namespace wifi { +namespace V1_0 { +namespace implementation { /** * Class that stores common state and functionality shared between HAL services. @@ -41,11 +43,7 @@ class WifiHalState { /** opaque handle from vendor for use while HAL is running */ wifi_handle hal_handle_; - enum class RunState { - STOPPED, - STARTED, - STOPPING - }; + enum class RunState { STOPPED, STARTED, STOPPING }; RunState run_state_; @@ -55,6 +53,8 @@ class WifiHalState { DISALLOW_COPY_AND_ASSIGN(WifiHalState); }; +} // namespace implementation +} // namespace V1_0 } // namespace wifi } // namespace hardware } // namespace android From aabe5755365b07b92f75e2ece853f44d785517aa Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Thu, 29 Sep 2016 09:03:59 -0700 Subject: [PATCH 3/8] 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 --- wifi/1.0/default/Android.mk | 2 +- wifi/1.0/default/service.cpp | 7 +- wifi/1.0/default/wifi.cpp | 144 +++++++-------------------- wifi/1.0/default/wifi.h | 38 ++----- wifi/1.0/default/wifi_chip.cpp | 52 ++-------- wifi/1.0/default/wifi_chip.h | 24 ++--- wifi/1.0/default/wifi_hal_state.cpp | 60 ----------- wifi/1.0/default/wifi_hal_state.h | 62 ------------ wifi/1.0/default/wifi_legacy_hal.cpp | 139 ++++++++++++++++++++++++++ wifi/1.0/default/wifi_legacy_hal.h | 67 +++++++++++++ 10 files changed, 281 insertions(+), 314 deletions(-) delete mode 100644 wifi/1.0/default/wifi_hal_state.cpp delete mode 100644 wifi/1.0/default/wifi_hal_state.h create mode 100644 wifi/1.0/default/wifi_legacy_hal.cpp create mode 100644 wifi/1.0/default/wifi_legacy_hal.h diff --git a/wifi/1.0/default/Android.mk b/wifi/1.0/default/Android.mk index 6180efdf9b..14923f5925 100644 --- a/wifi/1.0/default/Android.mk +++ b/wifi/1.0/default/Android.mk @@ -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 \ diff --git a/wifi/1.0/default/service.cpp b/wifi/1.0/default/service.cpp index 07e6c81e0d..10ce1dbadd 100644 --- a/wifi/1.0/default/service.cpp +++ b/wifi/1.0/default/service.cpp @@ -55,13 +55,14 @@ int main(int /*argc*/, char** argv) { // Setup hwbinder service android::sp 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 aa0fc5b65f..d5b69b815d 100644 --- a/wifi/1.0/default/wifi.cpp +++ b/wifi/1.0/default/wifi.cpp @@ -17,31 +17,18 @@ #include "wifi.h" #include -#include #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) : 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 Wifi::registerEventCallback( const sp& callback) { @@ -51,131 +38,76 @@ Return Wifi::registerEventCallback( } Return Wifi::isStarted() { - return state_.run_state_ != RunState::STOPPED; + return run_state_ != RunState::STOPPED; } Return 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 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 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 01227418a1..e6cf1acbe8 100644 --- a/wifi/1.0/default/wifi.h +++ b/wifi/1.0/default/wifi.h @@ -19,15 +19,13 @@ #include #include -#include #include #include -#include #include -#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); + Wifi(); + // HIDL methods exposed. Return registerEventCallback( const sp& callback) override; - Return isStarted() override; Return start() override; Return stop() override; - Return 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 legacy_hal_; + RunState run_state_; std::set> callbacks_; sp 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 42118b75d2..91cf5145a8 100644 --- a/wifi/1.0/default/wifi_chip.cpp +++ b/wifi/1.0/default/wifi_chip.cpp @@ -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 legacy_hal) + : legacy_hal_(legacy_hal) {} -void WifiChip::Invalidate() { - hal_state_ = nullptr; +void WifiChip::invalidate() { + legacy_hal_.reset(); callbacks_.clear(); } Return WifiChip::registerEventCallback( const sp& 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 WifiChip::registerEventCallback( } Return WifiChip::getAvailableModes(getAvailableModes_cb cb) { - if (!hal_state_) { + if (!legacy_hal_.lock()) { cb(hidl_vec()); return Void(); } else { @@ -55,54 +54,23 @@ Return WifiChip::getAvailableModes(getAvailableModes_cb cb) { } Return WifiChip::configureChip(uint32_t /*mode_id*/) { - if (!hal_state_) + if (!legacy_hal_.lock()) return Void(); // TODO add implementation return Void(); } Return WifiChip::getMode() { - if (!hal_state_) + if (!legacy_hal_.lock()) return 0; // TODO add implementation return 0; } Return WifiChip::requestChipDebugInfo() { - if (!hal_state_) + if (!legacy_hal_.lock()) return Void(); - - IWifiChipEventCallback::ChipDebugInfo result; - result.driverDescription = ""; - result.firmwareDescription = ""; - 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 d776644581..95fabe465e 100644 --- a/wifi/1.0/default/wifi_chip.h +++ b/wifi/1.0/default/wifi_chip.h @@ -21,9 +21,8 @@ #include #include -#include -#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 legacy_hal); + // Invalidate this instance once the HAL is stopped. + void invalidate(); + // HIDL methods exposed. Return registerEventCallback( const sp& callback) override; - Return getAvailableModes(getAvailableModes_cb cb) override; - Return configureChip(uint32_t mode_id) override; - Return getMode() override; - Return requestChipDebugInfo() override; - Return requestDriverDebugDump() override; - Return requestFirmwareDebugDump() override; private: - WifiHalState* hal_state_; - wifi_interface_handle interface_handle_; + std::weak_ptr legacy_hal_; std::set> 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 148368996a..0000000000 --- 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 -#include -#include - -namespace { -class FunctionMessageHandler : public android::MessageHandler { - public: - explicit FunctionMessageHandler(const std::function& callback) - : callback_(callback) {} - - ~FunctionMessageHandler() override = default; - - virtual void handleMessage(const android::Message& /*message*/) { - callback_(); - } - - private: - const std::function callback_; - - DISALLOW_COPY_AND_ASSIGN(FunctionMessageHandler); -}; -} - -namespace android { -namespace hardware { -namespace wifi { -namespace V1_0 { -namespace implementation { - -WifiHalState::WifiHalState(sp& looper) - : run_state_(RunState::STOPPED), looper_(looper) {} - -void WifiHalState::PostTask(const std::function& callback) { - sp 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 40e39ec424..0000000000 --- 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 - -#include -#include -#include - -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); - - /** Post a task to be executed on the main thread */ - void PostTask(const std::function& 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_; - - 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 0000000000..a9ad0d172e --- /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 + +#include "failure_reason_util.h" +#include "wifi_legacy_hal.h" + +#include +#include + +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 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& 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 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 0000000000..1af9f1a2f6 --- /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 +#include + +#include + +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& 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_ From 908a69a53a90945c351a3d97da4cb1b9c0d7c8c3 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Mon, 3 Oct 2016 13:33:23 -0700 Subject: [PATCH 4/8] wifi: Use hal_tool & if_tool Changes in the CL: 1. Currently |WifiNative.cpp|, uses |hal_tool| to initialize the function table and |if_tool| to set the interface up when |startHAL| method is invoked. Use the same sequence in the HIDL'ized HAL. 2. Remove the assertion if the function table initialization fails. This will result in a failure indication on starting the HAL now. Bug: 31352200 Test: mmma -j32 hardware/interfaces/wifi/1.0/default Change-Id: I268845ed62158b6a2ff36659f0bb15c4100a7222 --- wifi/1.0/default/Android.mk | 6 ++++-- wifi/1.0/default/wifi_legacy_hal.cpp | 20 ++++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/wifi/1.0/default/Android.mk b/wifi/1.0/default/Android.mk index 14923f5925..07865a5df7 100644 --- a/wifi/1.0/default/Android.mk +++ b/wifi/1.0/default/Android.mk @@ -30,7 +30,8 @@ LOCAL_SHARED_LIBRARIES := \ libhwbinder \ liblog \ libnl \ - libutils + libutils \ + libwifi-system LOCAL_WHOLE_STATIC_LIBRARIES := $(LIB_WIFI_HAL) include $(BUILD_SHARED_LIBRARY) @@ -49,7 +50,8 @@ LOCAL_SHARED_LIBRARIES := \ libhwbinder \ liblog \ libnl \ - libutils + libutils \ + libwifi-system 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/wifi_legacy_hal.cpp b/wifi/1.0/default/wifi_legacy_hal.cpp index a9ad0d172e..e755feace2 100644 --- a/wifi/1.0/default/wifi_legacy_hal.cpp +++ b/wifi/1.0/default/wifi_legacy_hal.cpp @@ -21,6 +21,8 @@ #include #include +#include +#include namespace { std::string getWlanInterfaceName() { @@ -50,16 +52,24 @@ 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"; -} + awaiting_event_loop_termination_(false) {} wifi_error WifiLegacyHal::start() { // Ensure that we're starting in a good state. CHECK(!global_handle_ && !wlan_interface_handle_ && !awaiting_event_loop_termination_); + android::wifi_system::HalTool hal_tool; + android::wifi_system::InterfaceTool if_tool; + if (!hal_tool.InitFunctionTable(&global_func_table_)) { + LOG(ERROR) << "Failed to initialize legacy hal function table"; + return WIFI_ERROR_UNKNOWN; + } + if (!if_tool.SetWifiUpState(true)) { + LOG(ERROR) << "Failed to set WiFi interface up"; + return WIFI_ERROR_UNKNOWN; + } + LOG(INFO) << "Starting legacy HAL"; wifi_error status = global_func_table_.wifi_initialize(&global_handle_); if (status != WIFI_SUCCESS || !global_handle_) { @@ -130,6 +140,8 @@ void WifiLegacyHal::runEventLoop() { } LOG(VERBOSE) << "Legacy HAL event loop terminated"; awaiting_event_loop_termination_ = false; + android::wifi_system::InterfaceTool if_tool; + if_tool.SetWifiUpState(false); } } // namespace implementation From 4b26c832ed66ea6c999c4fc38a3ec04b60e302e7 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Mon, 3 Oct 2016 12:49:58 -0700 Subject: [PATCH 5/8] wifi: Add Implementation of IWifiChip.requestChipDebugInfo Bug: 31352200 Test: mmma -j32 hardware/interfaces/wifi/1.0/default Change-Id: Id0c02e37dac66de6f830785881cb67f113c0fb19 --- wifi/1.0/default/wifi_chip.cpp | 24 +++++++++++++++++++++++- wifi/1.0/default/wifi_legacy_hal.cpp | 18 ++++++++++++++++++ wifi/1.0/default/wifi_legacy_hal.h | 5 +++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/wifi/1.0/default/wifi_chip.cpp b/wifi/1.0/default/wifi_chip.cpp index 91cf5145a8..e829924ffa 100644 --- a/wifi/1.0/default/wifi_chip.cpp +++ b/wifi/1.0/default/wifi_chip.cpp @@ -70,7 +70,29 @@ Return WifiChip::getMode() { Return WifiChip::requestChipDebugInfo() { if (!legacy_hal_.lock()) return Void(); - // TODO add implementation + + IWifiChipEventCallback::ChipDebugInfo result; + + std::pair ret = + legacy_hal_.lock()->getWlanDriverVersion(); + if (ret.first != WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get driver version: " + << LegacyErrorToString(ret.first); + return Void(); + } + result.driverDescription = ret.second.c_str(); + + ret = legacy_hal_.lock()->getWlanFirmwareVersion(); + if (ret.first != WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get firmware version: " + << LegacyErrorToString(ret.first); + return Void(); + } + result.firmwareDescription = ret.second.c_str(); + + for (const auto& callback : callbacks_) { + callback->onChipDebugInfoAvailable(result); + } return Void(); } diff --git a/wifi/1.0/default/wifi_legacy_hal.cpp b/wifi/1.0/default/wifi_legacy_hal.cpp index e755feace2..e3ae109442 100644 --- a/wifi/1.0/default/wifi_legacy_hal.cpp +++ b/wifi/1.0/default/wifi_legacy_hal.cpp @@ -49,6 +49,8 @@ namespace wifi { namespace V1_0 { namespace implementation { +const uint32_t WifiLegacyHal::kMaxVersionStringLength = 256; + WifiLegacyHal::WifiLegacyHal() : global_handle_(nullptr), wlan_interface_handle_(nullptr), @@ -102,6 +104,22 @@ wifi_error WifiLegacyHal::stop( return WIFI_SUCCESS; } +std::pair WifiLegacyHal::getWlanDriverVersion() { + std::array buffer; + buffer.fill(0); + wifi_error status = global_func_table_.wifi_get_driver_version( + wlan_interface_handle_, buffer.data(), buffer.size()); + return std::make_pair(status, buffer.data()); +} + +std::pair WifiLegacyHal::getWlanFirmwareVersion() { + std::array buffer; + buffer.fill(0); + wifi_error status = global_func_table_.wifi_get_firmware_version( + wlan_interface_handle_, buffer.data(), buffer.size()); + return std::make_pair(status, buffer.data()); +} + wifi_error WifiLegacyHal::retrieveWlanInterfaceHandle() { const std::string& ifname_to_find = getWlanInterfaceName(); diff --git a/wifi/1.0/default/wifi_legacy_hal.h b/wifi/1.0/default/wifi_legacy_hal.h index 1af9f1a2f6..e2a160e1ed 100644 --- a/wifi/1.0/default/wifi_legacy_hal.h +++ b/wifi/1.0/default/wifi_legacy_hal.h @@ -39,8 +39,13 @@ class WifiLegacyHal { wifi_error start(); // Deinitialize the legacy HAL and stop the event looper thread. wifi_error stop(const std::function& on_complete_callback); + // Wrappers for all the functions in the legacy HAL function table. + std::pair getWlanDriverVersion(); + std::pair getWlanFirmwareVersion(); private: + static const uint32_t kMaxVersionStringLength; + // Retrieve the interface handle to be used for the "wlan" interface. wifi_error retrieveWlanInterfaceHandle(); // Run the legacy HAL event loop thread. From cdb77f3cf2d285c2097fb62f5f9363accf146834 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Mon, 3 Oct 2016 14:09:57 -0700 Subject: [PATCH 6/8] wifi: Add implementation of driver/firmware memory dumps Bug: 31352200 Test: mmma -j32 hardware/interfaces/wifi/1.0/default Change-Id: I25d42cfd4c2b1ea7e63bdc036f37f81aed93c565 --- wifi/1.0/default/wifi_chip.cpp | 38 +++++++++++++++++++++++-- wifi/1.0/default/wifi_legacy_hal.cpp | 42 ++++++++++++++++++++++++++++ wifi/1.0/default/wifi_legacy_hal.h | 2 ++ 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/wifi/1.0/default/wifi_chip.cpp b/wifi/1.0/default/wifi_chip.cpp index e829924ffa..df321e2103 100644 --- a/wifi/1.0/default/wifi_chip.cpp +++ b/wifi/1.0/default/wifi_chip.cpp @@ -97,12 +97,46 @@ Return WifiChip::requestChipDebugInfo() { } Return WifiChip::requestDriverDebugDump() { - // TODO implement + if (!legacy_hal_.lock()) + return Void(); + + std::pair> ret = + legacy_hal_.lock()->requestWlanDriverMemoryDump(); + if (ret.first != WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get driver debug dump: " + << LegacyErrorToString(ret.first); + return Void(); + } + + auto& driver_dump = ret.second; + hidl_vec hidl_data; + hidl_data.setToExternal(reinterpret_cast(driver_dump.data()), + driver_dump.size()); + for (const auto& callback : callbacks_) { + callback->onDriverDebugDumpAvailable(hidl_data); + } return Void(); } Return WifiChip::requestFirmwareDebugDump() { - // TODO implement + if (!legacy_hal_.lock()) + return Void(); + + std::pair> ret = + legacy_hal_.lock()->requestWlanFirmwareMemoryDump(); + if (ret.first != WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get firmware debug dump: " + << LegacyErrorToString(ret.first); + return Void(); + } + + auto& firmware_dump = ret.second; + hidl_vec hidl_data; + hidl_data.setToExternal(reinterpret_cast(firmware_dump.data()), + firmware_dump.size()); + for (const auto& callback : callbacks_) { + callback->onFirmwareDebugDumpAvailable(hidl_data); + } return Void(); } diff --git a/wifi/1.0/default/wifi_legacy_hal.cpp b/wifi/1.0/default/wifi_legacy_hal.cpp index e3ae109442..a6df996fc1 100644 --- a/wifi/1.0/default/wifi_legacy_hal.cpp +++ b/wifi/1.0/default/wifi_legacy_hal.cpp @@ -41,6 +41,22 @@ void onStopComplete(wifi_handle handle) { on_stop_complete_internal_callback(handle); } } + +// Callback to be invoked for driver dump. +std::function on_driver_memory_dump_internal_callback; +void onDriverMemoryDump(char* buffer, int buffer_size) { + if (on_driver_memory_dump_internal_callback) { + on_driver_memory_dump_internal_callback(buffer, buffer_size); + } +} + +// Callback to be invoked for firmware dump. +std::function on_firmware_memory_dump_internal_callback; +void onFirmwareMemoryDump(char* buffer, int buffer_size) { + if (on_firmware_memory_dump_internal_callback) { + on_firmware_memory_dump_internal_callback(buffer, buffer_size); + } +} } namespace android { @@ -120,6 +136,32 @@ std::pair WifiLegacyHal::getWlanFirmwareVersion() { return std::make_pair(status, buffer.data()); } +std::pair> +WifiLegacyHal::requestWlanDriverMemoryDump() { + std::vector driver_dump; + on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer, + int buffer_size) { + driver_dump.insert(driver_dump.end(), buffer, buffer + buffer_size); + }; + wifi_error status = global_func_table_.wifi_get_driver_memory_dump( + wlan_interface_handle_, {onDriverMemoryDump}); + on_driver_memory_dump_internal_callback = nullptr; + return std::make_pair(status, std::move(driver_dump)); +} + +std::pair> +WifiLegacyHal::requestWlanFirmwareMemoryDump() { + std::vector firmware_dump; + on_firmware_memory_dump_internal_callback = [&firmware_dump]( + char* buffer, int buffer_size) { + firmware_dump.insert(firmware_dump.end(), buffer, buffer + buffer_size); + }; + wifi_error status = global_func_table_.wifi_get_firmware_memory_dump( + wlan_interface_handle_, {onFirmwareMemoryDump}); + on_firmware_memory_dump_internal_callback = nullptr; + return std::make_pair(status, std::move(firmware_dump)); +} + wifi_error WifiLegacyHal::retrieveWlanInterfaceHandle() { const std::string& ifname_to_find = getWlanInterfaceName(); diff --git a/wifi/1.0/default/wifi_legacy_hal.h b/wifi/1.0/default/wifi_legacy_hal.h index e2a160e1ed..f691b9ba5c 100644 --- a/wifi/1.0/default/wifi_legacy_hal.h +++ b/wifi/1.0/default/wifi_legacy_hal.h @@ -42,6 +42,8 @@ class WifiLegacyHal { // Wrappers for all the functions in the legacy HAL function table. std::pair getWlanDriverVersion(); std::pair getWlanFirmwareVersion(); + std::pair> requestWlanDriverMemoryDump(); + std::pair> requestWlanFirmwareMemoryDump(); private: static const uint32_t kMaxVersionStringLength; From 6f31d92e59d25130ae67a29022f9255bd19029ae Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 4 Oct 2016 15:08:05 -0700 Subject: [PATCH 7/8] wifi(interface): Add/Correct docstring params Changes in the CL: 1. Add missing docstring params in the HIDL interface. 2. Reword some method docs. Occurences of "will" is replaced by "must" (based on comments received on supplicant HIDL interface: go/aog/275115). 3. Add onFailure callbacks for all the methods and added docstrings for them. Bug: 31352200 Test: mmma -j32 hardware/interfaces/wifi/1.0 Change-Id: Ib7152625851023d6244f742bb77a8fdc0829e00d --- wifi/1.0/IWifi.hal | 10 ++++++-- wifi/1.0/IWifiChip.hal | 28 +++++++++++++++------ wifi/1.0/IWifiChipEventCallback.hal | 38 +++++++++++++++++++++++++---- wifi/1.0/IWifiEventCallback.hal | 4 +++ 4 files changed, 66 insertions(+), 14 deletions(-) diff --git a/wifi/1.0/IWifi.hal b/wifi/1.0/IWifi.hal index 1feeb2a9f4..d1311f5462 100644 --- a/wifi/1.0/IWifi.hal +++ b/wifi/1.0/IWifi.hal @@ -28,8 +28,12 @@ interface IWifi { /** * Requests notifications of significant events for the HAL. Multiple calls to * this must register multiple callbacks each of which must receive all - * events. IWifiEventCallback registration must be independent of the state - * of the rest of the HAL and must persist though stops/starts. + * events. |IWifiEventCallback| object registration must be independent of the + * state of the rest of the HAL and must persist though stops/starts. These + * objects must be deleted when the corresponding client process is dead. + * + * @param callback An instance of the |IWifiEventCallback| HIDL interface + * object. */ @entry @callflow(next={"*"}) @@ -37,6 +41,8 @@ interface IWifi { /** * Get the current state of the HAL. + * + * @return started true if started, false otherwise. */ isStarted() generates (bool started); diff --git a/wifi/1.0/IWifiChip.hal b/wifi/1.0/IWifiChip.hal index f5fe7a9e82..3e229e210c 100644 --- a/wifi/1.0/IWifiChip.hal +++ b/wifi/1.0/IWifiChip.hal @@ -125,41 +125,55 @@ interface IWifiChip { * Requests notifications of significant events on this chip. Multiple calls * to this will register multiple callbacks each of which will receive all * events. + * + * @param callback An instance of the |IWifiChipEventCallback| HIDL interface + * object. */ oneway registerEventCallback(IWifiChipEventCallback callback); /** * Get the set of operation modes that the chip supports. + * + * @return modes List of modes supported by the device. */ getAvailableModes() generates (vec modes); /** - * Reconfigure the Chip. Will trigger onChipReconfigured. + * Reconfigure the Chip. + * Must trigger |IWifiChipEventCallback.onChipReconfigured| on sucess, + * or |IWifiChipEventCallback.onChipReconfigureFailure| on failure. * * @param modeId The mode that the chip should switch to, corresponding to the - * id property of the target ChipMode. + * id property of the target ChipMode. */ oneway configureChip(ChipModeId modeId); /** * Get the current mode that the chip is in. + * + * @return modeId The mode that the chip is currently configured to, + * corresponding to the id property of the target ChipMode. */ getMode() generates (ChipModeId modeId); /** - * Request information about the chip. Will trigger onChipDebugInfoAvailable. + * Request information about the chip. + * Must trigger |IWifiChipEventCallback.onChipDebugInfoAvailable| on sucess, + * or |IWifiChipEventCallback.onChipDebugInfoFailure| on failure. */ oneway requestChipDebugInfo(); /** - * Request vendor debug info from the driver. Will trigger - * onDriverDebugDumpAvailable. + * Request vendor debug info from the driver. + * Must trigger |IWifiChipEventCallback.onDriverDebugDumpAvailable| on success, + * or |IWifiChipEventCallback.onDriverDebugDumpFailure| on failure. */ oneway requestDriverDebugDump(); /** - * Request vendor debug info from the firmware. Will trigger - * onFirmwareDebugDumpAvailable. + * Request vendor debug info from the firmware. + * Must trigger |IWifiChipEventCallback.onFirmwareDebugDumpAvailable| on + * success, or |IWifiChipEventCallback.onFirmwareDebugDumpFailure| on failure. */ oneway requestFirmwareDebugDump(); }; diff --git a/wifi/1.0/IWifiChipEventCallback.hal b/wifi/1.0/IWifiChipEventCallback.hal index 79f6d2a764..2161c5d4a7 100644 --- a/wifi/1.0/IWifiChipEventCallback.hal +++ b/wifi/1.0/IWifiChipEventCallback.hal @@ -24,7 +24,7 @@ interface IWifiChipEventCallback { * considered invalid. * * @param modeId The mode that the chip switched to, corresponding to the id - * property of the target ChipMode. + * property of the target ChipMode. */ oneway onChipReconfigured(ChipModeId modeId); @@ -34,7 +34,8 @@ interface IWifiChipEventCallback { * assumed to be invalid. * * @param modeId The mode that the chip failed switched to, corresponding to - * the id property of the target ChipMode. + * the id property of the target ChipMode. + * @param reason Failure reason code. */ oneway onChipReconfigureFailure(ChipModeId modeId, FailureReason reason); @@ -51,18 +52,45 @@ interface IWifiChipEventCallback { /** * Callback with debug information about this chip + * + * @param info Instance of |ChipDebugInfo|. */ oneway onChipDebugInfoAvailable(ChipDebugInfo info); /** - * Callback with a vendor specific debug blob from the driver. - * This blob will be dumped as part of the bug report. + * Callback to be invoked on failure to fetch debug info about this chip. + * + * @param reason Failure reason code. */ - oneway onDriverDebugDumpAvailable(vec blob); + oneway onChipDebugInfoFailure(FailureReason reason); /** * Callback with a vendor specific debug blob from the driver. * This blob will be dumped as part of the bug report. + * + * @param blob Vector of bytes retrieved from the driver. + */ + oneway onDriverDebugDumpAvailable(vec blob); + + /** + * Callback to be invoked on failure to fetch debug blob from driver. + * + * @param reason Failure reason code. + */ + oneway onDriverDebugDumpFailure(FailureReason reason); + + /** + * Callback with a vendor specific debug blob from the driver. + * This blob will be dumped as part of the bug report. + * + * @param blob Vector of bytes retrieved from the driver. */ oneway onFirmwareDebugDumpAvailable(vec blob); + + /** + * Callback to be invoked on failure to fetch debug blob from driver. + * + * @param reason Failure reason code. + */ + oneway onFirmwareDebugDumpFailure(FailureReason reason); }; diff --git a/wifi/1.0/IWifiEventCallback.hal b/wifi/1.0/IWifiEventCallback.hal index 84025cec9f..33accff8ea 100644 --- a/wifi/1.0/IWifiEventCallback.hal +++ b/wifi/1.0/IWifiEventCallback.hal @@ -28,6 +28,8 @@ interface IWifiEventCallback { * failed. After this callback the HAL will be considered stopped. Another * call to start will attempt to reinitialize the HAL; however, there is a * chance it may fail again. + * + * @param reason Failure reason code. */ oneway onStartFailure(FailureReason reason); @@ -43,6 +45,8 @@ interface IWifiEventCallback { * Calling start again must restart Wi-Fi as if stop then start was called * (full state reset). When this event is received all IWifiChip objects * retrieved after the last call to start will be considered invalid. + * + * @param reason Failure reason code. */ oneway onFailure(FailureReason reason); }; From 271f2c2d9ca5760a1cdd591bf426127077f6c683 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 4 Oct 2016 17:01:01 -0700 Subject: [PATCH 8/8] wifi(interface): Rename interface to iface The HIDL objects are called "interface", so rename the wifi interface to iface to distinguish between them better. This is especially needed in the follow up CL. Bug: 31943042 Test: mmm -j32 hardware/interfaces/wifi/1.0/ Change-Id: I3bc34930f75159d26321c0e071af9084d0585508 --- wifi/1.0/IWifiChip.hal | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/wifi/1.0/IWifiChip.hal b/wifi/1.0/IWifiChip.hal index 3e229e210c..7a41ddf1b7 100644 --- a/wifi/1.0/IWifiChip.hal +++ b/wifi/1.0/IWifiChip.hal @@ -24,7 +24,7 @@ import IWifiChipEventCallback; * to perform operations like NAN, RTT, etc. */ interface IWifiChip { - enum InterfaceType : uint32_t { + enum IfaceType : uint32_t { STA, AP, P2P, /** * NAN control interface. Datapath support may be queried and created @@ -35,11 +35,11 @@ interface IWifiChip { /** * Set of interface types with the maximum number of interfaces that can have - * one of the specified type for a given ChipInterfaceCombination. See - * ChipInterfaceCombination for examples. + * one of the specified type for a given ChipIfaceCombination. See + * ChipIfaceCombination for examples. */ - struct ChipInterfaceCombinationLimit { - vec types; // Each InterfaceType may occur at most once + struct ChipIfaceCombinationLimit { + vec types; // Each IfaceType may occur at most once uint32_t maxIfaces; }; @@ -66,8 +66,8 @@ interface IWifiChip { * [], [STA], [STA+NAN], [STA+STA], [NAN] * Not included [STA+STA+NAN] */ - struct ChipInterfaceCombination { - vec limits; + struct ChipIfaceCombination { + vec limits; }; /** @@ -80,7 +80,7 @@ interface IWifiChip { * * When in a mode, it must be possible to perform any combination of creating * and removing interfaces as long as at least one of the - * ChipInterfaceCombinations is satisfied. This means that if a chip has two + * ChipIfaceCombinations is satisfied. This means that if a chip has two * available combinations, [{STA} <= 1] and [{AP} <= 1] then it is expected * that exactly one STA interface or one AP interface can be created, but it * is not expected that both a STA and AP interface could be created. If it @@ -118,7 +118,7 @@ interface IWifiChip { * A list of the possible interface combinations that the chip can have * while in this mode. */ - vec availableCombinations; + vec availableCombinations; }; /**