diff options
37 files changed, 10993 insertions, 0 deletions
diff --git a/wifi/1.0/Android.mk b/wifi/1.0/Android.mk new file mode 100644 index 0000000..ae084e2 --- /dev/null +++ b/wifi/1.0/Android.mk @@ -0,0 +1,102 @@ +# 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) + +### +### android.hardware.wifi static library +### +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.wifi@1.0-service-lib +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_PROPRIETARY_MODULE := true +LOCAL_CPPFLAGS := -Wall -Werror -Wextra +ifdef WIFI_HAL_INTERFACE_COMBINATIONS +LOCAL_CPPFLAGS += -DWIFI_HAL_INTERFACE_COMBINATIONS="$(WIFI_HAL_INTERFACE_COMBINATIONS)" +endif +ifdef WIFI_HIDL_FEATURE_AWARE +LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_AWARE +endif +ifdef WIFI_HIDL_FEATURE_DUAL_INTERFACE +LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DUAL_INTERFACE +endif +ifdef WIFI_HIDL_FEATURE_DISABLE_AP +LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DISABLE_AP +endif +ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION +LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION +endif +# Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed. +LOCAL_CFLAGS += -Wno-error=implicit-fallthrough +LOCAL_SRC_FILES := \ + hidl_struct_util.cpp \ + hidl_sync_util.cpp \ + ringbuffer.cpp \ + wifi.cpp \ + wifi_ap_iface.cpp \ + wifi_chip.cpp \ + wifi_feature_flags.cpp \ + wifi_iface_util.cpp \ + wifi_legacy_hal.cpp \ + wifi_legacy_hal_stubs.cpp \ + wifi_mode_controller.cpp \ + wifi_nan_iface.cpp \ + wifi_p2p_iface.cpp \ + wifi_rtt_controller.cpp \ + wifi_sta_iface.cpp \ + wifi_status_util.cpp +LOCAL_SHARED_LIBRARIES := \ + libbase \ + libcutils \ + libhidlbase \ + libhidltransport \ + liblog \ + libnl \ + libutils \ + libwifi-hal \ + libwifi-system-iface \ + android.hardware.wifi@1.0 \ + android.hardware.wifi@1.1 \ + android.hardware.wifi@1.2 \ + android.hardware.wifi@1.3 +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) +include $(BUILD_STATIC_LIBRARY) + +### +### android.hardware.wifi daemon +### +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.wifi@1.0-service +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_PROPRIETARY_MODULE := true +LOCAL_CPPFLAGS := -Wall -Werror -Wextra +LOCAL_SRC_FILES := \ + service.cpp +LOCAL_SHARED_LIBRARIES := \ + libbase \ + libcutils \ + libhidlbase \ + libhidltransport \ + liblog \ + libnl \ + libutils \ + libwifi-hal \ + libwifi-system-iface \ + android.hardware.wifi@1.0 \ + android.hardware.wifi@1.1 \ + android.hardware.wifi@1.2 \ + android.hardware.wifi@1.3 +LOCAL_STATIC_LIBRARIES := \ + android.hardware.wifi@1.0-service-lib +LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc +include $(BUILD_EXECUTABLE) diff --git a/wifi/1.0/android.hardware.wifi@1.0-service.rc b/wifi/1.0/android.hardware.wifi@1.0-service.rc new file mode 100644 index 0000000..cf849d0 --- /dev/null +++ b/wifi/1.0/android.hardware.wifi@1.0-service.rc @@ -0,0 +1,5 @@ +service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service + class hal + capabilities NET_ADMIN NET_RAW SYS_MODULE + user wifi + group wifi gps diff --git a/wifi/1.0/hidl_callback_util.h b/wifi/1.0/hidl_callback_util.h new file mode 100644 index 0000000..a44af79 --- /dev/null +++ b/wifi/1.0/hidl_callback_util.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2017 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 HIDL_CALLBACK_UTIL_H_ +#define HIDL_CALLBACK_UTIL_H_ + +#include <set> + +#include <hidl/HidlSupport.h> + +namespace { +// Type of callback invoked by the death handler. +using on_death_cb_function = std::function<void(uint64_t)>; + +// Private class used to keep track of death of individual +// callbacks stored in HidlCallbackHandler. +template <typename CallbackType> +class HidlDeathHandler : public android::hardware::hidl_death_recipient { + public: + HidlDeathHandler(const on_death_cb_function& user_cb_function) + : cb_function_(user_cb_function) {} + ~HidlDeathHandler() = default; + + // Death notification for callbacks. + void serviceDied( + uint64_t cookie, + const android::wp<android::hidl::base::V1_0::IBase>& /* who */) + override { + cb_function_(cookie); + } + + private: + on_death_cb_function cb_function_; + + DISALLOW_COPY_AND_ASSIGN(HidlDeathHandler); +}; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace hidl_callback_util { +template <typename CallbackType> +// Provides a class to manage callbacks for the various HIDL interfaces and +// handle the death of the process hosting each callback. +class HidlCallbackHandler { + public: + HidlCallbackHandler() + : death_handler_(new HidlDeathHandler<CallbackType>( + std::bind(&HidlCallbackHandler::onObjectDeath, this, + std::placeholders::_1))) {} + ~HidlCallbackHandler() = default; + + bool addCallback(const sp<CallbackType>& cb) { + // TODO(b/33818800): Can't compare proxies yet. So, use the cookie + // (callback proxy's raw pointer) to track the death of individual + // clients. + uint64_t cookie = reinterpret_cast<uint64_t>(cb.get()); + if (cb_set_.find(cb) != cb_set_.end()) { + LOG(WARNING) << "Duplicate death notification registration"; + return true; + } + if (!cb->linkToDeath(death_handler_, cookie)) { + LOG(ERROR) << "Failed to register death notification"; + return false; + } + cb_set_.insert(cb); + return true; + } + + const std::set<android::sp<CallbackType>>& getCallbacks() { + return cb_set_; + } + + // Death notification for callbacks. + void onObjectDeath(uint64_t cookie) { + CallbackType* cb = reinterpret_cast<CallbackType*>(cookie); + const auto& iter = cb_set_.find(cb); + if (iter == cb_set_.end()) { + LOG(ERROR) << "Unknown callback death notification received"; + return; + } + cb_set_.erase(iter); + LOG(DEBUG) << "Dead callback removed from list"; + } + + void invalidate() { + for (const sp<CallbackType>& cb : cb_set_) { + if (!cb->unlinkToDeath(death_handler_)) { + LOG(ERROR) << "Failed to deregister death notification"; + } + } + cb_set_.clear(); + } + + private: + std::set<sp<CallbackType>> cb_set_; + sp<HidlDeathHandler<CallbackType>> death_handler_; + + DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler); +}; + +} // namespace hidl_callback_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // HIDL_CALLBACK_UTIL_H_ diff --git a/wifi/1.0/hidl_return_util.h b/wifi/1.0/hidl_return_util.h new file mode 100644 index 0000000..9707444 --- /dev/null +++ b/wifi/1.0/hidl_return_util.h @@ -0,0 +1,120 @@ +/* + * 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 HIDL_RETURN_UTIL_H_ +#define HIDL_RETURN_UTIL_H_ + +#include "hidl_sync_util.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace hidl_return_util { +using namespace android::hardware::wifi::V1_0; + +/** + * These utility functions are used to invoke a method on the provided + * HIDL interface object. + * These functions checks if the provided HIDL interface object is valid. + * a) if valid, Invokes the corresponding internal implementation function of + * the HIDL method. It then invokes the HIDL continuation callback with + * the status and any returned values. + * b) if invalid, invokes the HIDL continuation callback with the + * provided error status and default values. + */ +// Use for HIDL methods which return only an instance of WifiStatus. +template <typename ObjT, typename WorkFuncT, typename... Args> +Return<void> validateAndCall( + ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work, + const std::function<void(const WifiStatus&)>& hidl_cb, Args&&... args) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + hidl_cb((obj->*work)(std::forward<Args>(args)...)); + } else { + hidl_cb(createWifiStatus(status_code_if_invalid)); + } + return Void(); +} + +// Use for HIDL methods which return only an instance of WifiStatus. +// This version passes the global lock acquired to the body of the method. +// Note: Only used by IWifi::stop() currently. +template <typename ObjT, typename WorkFuncT, typename... Args> +Return<void> validateAndCallWithLock( + ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work, + const std::function<void(const WifiStatus&)>& hidl_cb, Args&&... args) { + auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + hidl_cb((obj->*work)(&lock, std::forward<Args>(args)...)); + } else { + hidl_cb(createWifiStatus(status_code_if_invalid)); + } + return Void(); +} + +// Use for HIDL methods which return instance of WifiStatus and a single return +// value. +template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args> +Return<void> validateAndCall( + ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work, + const std::function<void(const WifiStatus&, ReturnT)>& hidl_cb, + Args&&... args) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + const auto& ret_pair = (obj->*work)(std::forward<Args>(args)...); + const WifiStatus& status = std::get<0>(ret_pair); + const auto& ret_value = std::get<1>(ret_pair); + hidl_cb(status, ret_value); + } else { + hidl_cb(createWifiStatus(status_code_if_invalid), + typename std::remove_reference<ReturnT>::type()); + } + return Void(); +} + +// Use for HIDL methods which return instance of WifiStatus and 2 return +// values. +template <typename ObjT, typename WorkFuncT, typename ReturnT1, + typename ReturnT2, typename... Args> +Return<void> validateAndCall( + ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work, + const std::function<void(const WifiStatus&, ReturnT1, ReturnT2)>& hidl_cb, + Args&&... args) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (obj->isValid()) { + const auto& ret_tuple = (obj->*work)(std::forward<Args>(args)...); + const WifiStatus& status = std::get<0>(ret_tuple); + const auto& ret_value1 = std::get<1>(ret_tuple); + const auto& ret_value2 = std::get<2>(ret_tuple); + hidl_cb(status, ret_value1, ret_value2); + } else { + hidl_cb(createWifiStatus(status_code_if_invalid), + typename std::remove_reference<ReturnT1>::type(), + typename std::remove_reference<ReturnT2>::type()); + } + return Void(); +} + +} // namespace hidl_return_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // HIDL_RETURN_UTIL_H_ diff --git a/wifi/1.0/hidl_struct_util.cpp b/wifi/1.0/hidl_struct_util.cpp new file mode 100644 index 0000000..2e4db70 --- /dev/null +++ b/wifi/1.0/hidl_struct_util.cpp @@ -0,0 +1,2689 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/logging.h> +#include <utils/SystemClock.h> + +#include "hidl_struct_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace hidl_struct_util { + +WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl( + legacy_hal::wifi_channel_width type); + +hidl_string safeConvertChar(const char* str, size_t max_len) { + const char* c = str; + size_t size = 0; + while (*c && (unsigned char)*c < 128 && size < max_len) { + ++size; + ++c; + } + return hidl_string(str, size); +} + +IWifiChip::ChipCapabilityMask convertLegacyLoggerFeatureToHidlChipCapability( + uint32_t feature) { + using HidlChipCaps = IWifiChip::ChipCapabilityMask; + switch (feature) { + case legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED: + return HidlChipCaps::DEBUG_MEMORY_FIRMWARE_DUMP; + case legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED: + return HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP; + case legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED: + return HidlChipCaps::DEBUG_RING_BUFFER_CONNECT_EVENT; + case legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED: + return HidlChipCaps::DEBUG_RING_BUFFER_POWER_EVENT; + case legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED: + return HidlChipCaps::DEBUG_RING_BUFFER_WAKELOCK_EVENT; + }; + CHECK(false) << "Unknown legacy feature: " << feature; + return {}; +} + +IWifiStaIface::StaIfaceCapabilityMask +convertLegacyLoggerFeatureToHidlStaIfaceCapability(uint32_t feature) { + using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask; + switch (feature) { + case legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED: + return HidlStaIfaceCaps::DEBUG_PACKET_FATE; + }; + CHECK(false) << "Unknown legacy feature: " << feature; + return {}; +} + +V1_3::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability( + uint32_t feature) { + using HidlChipCaps = V1_3::IWifiChip::ChipCapabilityMask; + switch (feature) { + case WIFI_FEATURE_SET_TX_POWER_LIMIT: + return HidlChipCaps::SET_TX_POWER_LIMIT; + case WIFI_FEATURE_USE_BODY_HEAD_SAR: + return HidlChipCaps::USE_BODY_HEAD_SAR; + case WIFI_FEATURE_D2D_RTT: + return HidlChipCaps::D2D_RTT; + case WIFI_FEATURE_D2AP_RTT: + return HidlChipCaps::D2AP_RTT; + case WIFI_FEATURE_SET_LATENCY_MODE: + return HidlChipCaps::SET_LATENCY_MODE; + case WIFI_FEATURE_P2P_RAND_MAC: + return HidlChipCaps::P2P_RAND_MAC; + }; + CHECK(false) << "Unknown legacy feature: " << feature; + return {}; +} + +IWifiStaIface::StaIfaceCapabilityMask +convertLegacyFeatureToHidlStaIfaceCapability(uint32_t feature) { + using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask; + switch (feature) { + case WIFI_FEATURE_GSCAN: + return HidlStaIfaceCaps::BACKGROUND_SCAN; + case WIFI_FEATURE_LINK_LAYER_STATS: + return HidlStaIfaceCaps::LINK_LAYER_STATS; + case WIFI_FEATURE_RSSI_MONITOR: + return HidlStaIfaceCaps::RSSI_MONITOR; + case WIFI_FEATURE_CONTROL_ROAMING: + return HidlStaIfaceCaps::CONTROL_ROAMING; + case WIFI_FEATURE_IE_WHITELIST: + return HidlStaIfaceCaps::PROBE_IE_WHITELIST; + case WIFI_FEATURE_SCAN_RAND: + return HidlStaIfaceCaps::SCAN_RAND; + case WIFI_FEATURE_INFRA_5G: + return HidlStaIfaceCaps::STA_5G; + case WIFI_FEATURE_HOTSPOT: + return HidlStaIfaceCaps::HOTSPOT; + case WIFI_FEATURE_PNO: + return HidlStaIfaceCaps::PNO; + case WIFI_FEATURE_TDLS: + return HidlStaIfaceCaps::TDLS; + case WIFI_FEATURE_TDLS_OFFCHANNEL: + return HidlStaIfaceCaps::TDLS_OFFCHANNEL; + case WIFI_FEATURE_CONFIG_NDO: + return HidlStaIfaceCaps::ND_OFFLOAD; + case WIFI_FEATURE_MKEEP_ALIVE: + return HidlStaIfaceCaps::KEEP_ALIVE; + }; + CHECK(false) << "Unknown legacy feature: " << feature; + return {}; +} + +bool convertLegacyFeaturesToHidlChipCapabilities( + uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set, + uint32_t* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + using HidlChipCaps = IWifiChip::ChipCapabilityMask; + for (const auto feature : {legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED, + legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED, + legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED, + legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED, + legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED}) { + if (feature & legacy_logger_feature_set) { + *hidl_caps |= + convertLegacyLoggerFeatureToHidlChipCapability(feature); + } + } + std::vector<uint32_t> features = {WIFI_FEATURE_SET_TX_POWER_LIMIT, + WIFI_FEATURE_USE_BODY_HEAD_SAR, + WIFI_FEATURE_D2D_RTT, + WIFI_FEATURE_D2AP_RTT, + WIFI_FEATURE_SET_LATENCY_MODE, + WIFI_FEATURE_P2P_RAND_MAC}; + for (const auto feature : features) { + if (feature & legacy_feature_set) { + *hidl_caps |= convertLegacyFeatureToHidlChipCapability(feature); + } + } + + // There are no flags for these 3 in the legacy feature set. Adding them to + // the set because all the current devices support it. + *hidl_caps |= HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA; + *hidl_caps |= HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS; + *hidl_caps |= HidlChipCaps::DEBUG_ERROR_ALERTS; + return true; +} + +WifiDebugRingBufferFlags convertLegacyDebugRingBufferFlagsToHidl( + uint32_t flag) { + switch (flag) { + case WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES: + return WifiDebugRingBufferFlags::HAS_BINARY_ENTRIES; + case WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES: + return WifiDebugRingBufferFlags::HAS_ASCII_ENTRIES; + }; + CHECK(false) << "Unknown legacy flag: " << flag; + return {}; +} + +bool convertLegacyDebugRingBufferStatusToHidl( + const legacy_hal::wifi_ring_buffer_status& legacy_status, + WifiDebugRingBufferStatus* hidl_status) { + if (!hidl_status) { + return false; + } + *hidl_status = {}; + hidl_status->ringName = + safeConvertChar(reinterpret_cast<const char*>(legacy_status.name), + sizeof(legacy_status.name)); + hidl_status->flags = 0; + for (const auto flag : {WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES, + WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES}) { + if (flag & legacy_status.flags) { + hidl_status->flags |= static_cast< + std::underlying_type<WifiDebugRingBufferFlags>::type>( + convertLegacyDebugRingBufferFlagsToHidl(flag)); + } + } + hidl_status->ringId = legacy_status.ring_id; + hidl_status->sizeInBytes = legacy_status.ring_buffer_byte_size; + // Calculate free size of the ring the buffer. We don't need to send the + // exact read/write pointers that were there in the legacy HAL interface. + if (legacy_status.written_bytes >= legacy_status.read_bytes) { + hidl_status->freeSizeInBytes = + legacy_status.ring_buffer_byte_size - + (legacy_status.written_bytes - legacy_status.read_bytes); + } else { + hidl_status->freeSizeInBytes = + legacy_status.read_bytes - legacy_status.written_bytes; + } + hidl_status->verboseLevel = legacy_status.verbose_level; + return true; +} + +bool convertLegacyVectorOfDebugRingBufferStatusToHidl( + const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec, + std::vector<WifiDebugRingBufferStatus>* hidl_status_vec) { + if (!hidl_status_vec) { + return false; + } + *hidl_status_vec = {}; + for (const auto& legacy_status : legacy_status_vec) { + WifiDebugRingBufferStatus hidl_status; + if (!convertLegacyDebugRingBufferStatusToHidl(legacy_status, + &hidl_status)) { + return false; + } + hidl_status_vec->push_back(hidl_status); + } + return true; +} + +bool convertLegacyWakeReasonStatsToHidl( + const legacy_hal::WakeReasonStats& legacy_stats, + WifiDebugHostWakeReasonStats* hidl_stats) { + if (!hidl_stats) { + return false; + } + *hidl_stats = {}; + hidl_stats->totalCmdEventWakeCnt = + legacy_stats.wake_reason_cnt.total_cmd_event_wake; + hidl_stats->cmdEventWakeCntPerType = legacy_stats.cmd_event_wake_cnt; + hidl_stats->totalDriverFwLocalWakeCnt = + legacy_stats.wake_reason_cnt.total_driver_fw_local_wake; + hidl_stats->driverFwLocalWakeCntPerType = + legacy_stats.driver_fw_local_wake_cnt; + hidl_stats->totalRxPacketWakeCnt = + legacy_stats.wake_reason_cnt.total_rx_data_wake; + hidl_stats->rxPktWakeDetails.rxUnicastCnt = + legacy_stats.wake_reason_cnt.rx_wake_details.rx_unicast_cnt; + hidl_stats->rxPktWakeDetails.rxMulticastCnt = + legacy_stats.wake_reason_cnt.rx_wake_details.rx_multicast_cnt; + hidl_stats->rxPktWakeDetails.rxBroadcastCnt = + legacy_stats.wake_reason_cnt.rx_wake_details.rx_broadcast_cnt; + hidl_stats->rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt = + legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info + .ipv4_rx_multicast_addr_cnt; + hidl_stats->rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt = + legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info + .ipv6_rx_multicast_addr_cnt; + hidl_stats->rxMulticastPkWakeDetails.otherRxMulticastAddrCnt = + legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info + .other_rx_multicast_addr_cnt; + hidl_stats->rxIcmpPkWakeDetails.icmpPkt = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp_pkt; + hidl_stats->rxIcmpPkWakeDetails.icmp6Pkt = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_pkt; + hidl_stats->rxIcmpPkWakeDetails.icmp6Ra = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ra; + hidl_stats->rxIcmpPkWakeDetails.icmp6Na = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_na; + hidl_stats->rxIcmpPkWakeDetails.icmp6Ns = + legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ns; + return true; +} + +legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy( + V1_1::IWifiChip::TxPowerScenario hidl_scenario) { + switch (hidl_scenario) { + // This is the only supported scenario for V1_1 + case V1_1::IWifiChip::TxPowerScenario::VOICE_CALL: + return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL; + }; + CHECK(false); +} + +legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2( + V1_2::IWifiChip::TxPowerScenario hidl_scenario) { + switch (hidl_scenario) { + // This is the only supported scenario for V1_1 + case V1_2::IWifiChip::TxPowerScenario::VOICE_CALL: + return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL; + // Those are the supported scenarios for V1_2 + case V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF: + return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF; + case V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_ON: + return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON; + case V1_2::IWifiChip::TxPowerScenario::ON_BODY_CELL_OFF: + return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF; + case V1_2::IWifiChip::TxPowerScenario::ON_BODY_CELL_ON: + return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON; + }; + CHECK(false); +} + +legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy( + IWifiChip::LatencyMode hidl_latency_mode) { + switch (hidl_latency_mode) { + case IWifiChip::LatencyMode::NORMAL: + return legacy_hal::WIFI_LATENCY_MODE_NORMAL; + case IWifiChip::LatencyMode::LOW: + return legacy_hal::WIFI_LATENCY_MODE_LOW; + } + CHECK(false); +} + +bool convertLegacyWifiMacInfoToHidl( + const legacy_hal::WifiMacInfo& legacy_mac_info, + V1_2::IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) { + if (!hidl_radio_mode_info) { + return false; + } + *hidl_radio_mode_info = {}; + + hidl_radio_mode_info->radioId = legacy_mac_info.wlan_mac_id; + // Convert from bitmask of bands in the legacy HAL to enum value in + // the HIDL interface. + if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND && + legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) { + hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ_5GHZ; + } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) { + hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ; + } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) { + hidl_radio_mode_info->bandInfo = WifiBand::BAND_5GHZ; + } else { + hidl_radio_mode_info->bandInfo = WifiBand::BAND_UNSPECIFIED; + } + std::vector<V1_2::IWifiChipEventCallback::IfaceInfo> iface_info_vec; + for (const auto& legacy_iface_info : legacy_mac_info.iface_infos) { + V1_2::IWifiChipEventCallback::IfaceInfo iface_info; + iface_info.name = legacy_iface_info.name; + iface_info.channel = legacy_iface_info.channel; + iface_info_vec.push_back(iface_info); + } + hidl_radio_mode_info->ifaceInfos = iface_info_vec; + return true; +} + +bool convertLegacyWifiMacInfosToHidl( + const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos, + std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo>* + hidl_radio_mode_infos) { + if (!hidl_radio_mode_infos) { + return false; + } + *hidl_radio_mode_infos = {}; + + for (const auto& legacy_mac_info : legacy_mac_infos) { + V1_2::IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info; + if (!convertLegacyWifiMacInfoToHidl(legacy_mac_info, + &hidl_radio_mode_info)) { + return false; + } + hidl_radio_mode_infos->push_back(hidl_radio_mode_info); + } + return true; +} + +bool convertLegacyFeaturesToHidlStaCapabilities( + uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set, + uint32_t* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask; + for (const auto feature : {legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED}) { + if (feature & legacy_logger_feature_set) { + *hidl_caps |= + convertLegacyLoggerFeatureToHidlStaIfaceCapability(feature); + } + } + for (const auto feature : + {WIFI_FEATURE_GSCAN, WIFI_FEATURE_LINK_LAYER_STATS, + WIFI_FEATURE_RSSI_MONITOR, WIFI_FEATURE_CONTROL_ROAMING, + WIFI_FEATURE_IE_WHITELIST, WIFI_FEATURE_SCAN_RAND, + WIFI_FEATURE_INFRA_5G, WIFI_FEATURE_HOTSPOT, WIFI_FEATURE_PNO, + WIFI_FEATURE_TDLS, WIFI_FEATURE_TDLS_OFFCHANNEL, + WIFI_FEATURE_CONFIG_NDO, WIFI_FEATURE_MKEEP_ALIVE}) { + if (feature & legacy_feature_set) { + *hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature); + } + } + // There is no flag for this one in the legacy feature set. Adding it to the + // set because all the current devices support it. + *hidl_caps |= HidlStaIfaceCaps::APF; + return true; +} + +bool convertLegacyApfCapabilitiesToHidl( + const legacy_hal::PacketFilterCapabilities& legacy_caps, + StaApfPacketFilterCapabilities* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + hidl_caps->version = legacy_caps.version; + hidl_caps->maxLength = legacy_caps.max_len; + return true; +} + +uint8_t convertHidlGscanReportEventFlagToLegacy( + StaBackgroundScanBucketEventReportSchemeMask hidl_flag) { + using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask; + switch (hidl_flag) { + case HidlFlag::EACH_SCAN: + return REPORT_EVENTS_EACH_SCAN; + case HidlFlag::FULL_RESULTS: + return REPORT_EVENTS_FULL_RESULTS; + case HidlFlag::NO_BATCH: + return REPORT_EVENTS_NO_BATCH; + }; + CHECK(false); +} + +StaScanDataFlagMask convertLegacyGscanDataFlagToHidl(uint8_t legacy_flag) { + switch (legacy_flag) { + case legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED: + return StaScanDataFlagMask::INTERRUPTED; + }; + CHECK(false) << "Unknown legacy flag: " << legacy_flag; + // To silence the compiler warning about reaching the end of non-void + // function. + return {}; +} + +bool convertLegacyGscanCapabilitiesToHidl( + const legacy_hal::wifi_gscan_capabilities& legacy_caps, + StaBackgroundScanCapabilities* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + hidl_caps->maxCacheSize = legacy_caps.max_scan_cache_size; + hidl_caps->maxBuckets = legacy_caps.max_scan_buckets; + hidl_caps->maxApCachePerScan = legacy_caps.max_ap_cache_per_scan; + hidl_caps->maxReportingThreshold = legacy_caps.max_scan_reporting_threshold; + return true; +} + +legacy_hal::wifi_band convertHidlWifiBandToLegacy(WifiBand band) { + switch (band) { + case WifiBand::BAND_UNSPECIFIED: + return legacy_hal::WIFI_BAND_UNSPECIFIED; + case WifiBand::BAND_24GHZ: + return legacy_hal::WIFI_BAND_BG; + case WifiBand::BAND_5GHZ: + return legacy_hal::WIFI_BAND_A; + case WifiBand::BAND_5GHZ_DFS: + return legacy_hal::WIFI_BAND_A_DFS; + case WifiBand::BAND_5GHZ_WITH_DFS: + return legacy_hal::WIFI_BAND_A_WITH_DFS; + case WifiBand::BAND_24GHZ_5GHZ: + return legacy_hal::WIFI_BAND_ABG; + case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS: + return legacy_hal::WIFI_BAND_ABG_WITH_DFS; + }; + CHECK(false); +} + +bool convertHidlGscanParamsToLegacy( + const StaBackgroundScanParameters& hidl_scan_params, + legacy_hal::wifi_scan_cmd_params* legacy_scan_params) { + if (!legacy_scan_params) { + return false; + } + *legacy_scan_params = {}; + legacy_scan_params->base_period = hidl_scan_params.basePeriodInMs; + legacy_scan_params->max_ap_per_scan = hidl_scan_params.maxApPerScan; + legacy_scan_params->report_threshold_percent = + hidl_scan_params.reportThresholdPercent; + legacy_scan_params->report_threshold_num_scans = + hidl_scan_params.reportThresholdNumScans; + if (hidl_scan_params.buckets.size() > MAX_BUCKETS) { + return false; + } + legacy_scan_params->num_buckets = hidl_scan_params.buckets.size(); + for (uint32_t bucket_idx = 0; bucket_idx < hidl_scan_params.buckets.size(); + bucket_idx++) { + const StaBackgroundScanBucketParameters& hidl_bucket_spec = + hidl_scan_params.buckets[bucket_idx]; + legacy_hal::wifi_scan_bucket_spec& legacy_bucket_spec = + legacy_scan_params->buckets[bucket_idx]; + if (hidl_bucket_spec.bucketIdx >= MAX_BUCKETS) { + return false; + } + legacy_bucket_spec.bucket = hidl_bucket_spec.bucketIdx; + legacy_bucket_spec.band = + convertHidlWifiBandToLegacy(hidl_bucket_spec.band); + legacy_bucket_spec.period = hidl_bucket_spec.periodInMs; + legacy_bucket_spec.max_period = + hidl_bucket_spec.exponentialMaxPeriodInMs; + legacy_bucket_spec.base = hidl_bucket_spec.exponentialBase; + legacy_bucket_spec.step_count = hidl_bucket_spec.exponentialStepCount; + legacy_bucket_spec.report_events = 0; + using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask; + for (const auto flag : {HidlFlag::EACH_SCAN, HidlFlag::FULL_RESULTS, + HidlFlag::NO_BATCH}) { + if (hidl_bucket_spec.eventReportScheme & + static_cast<std::underlying_type<HidlFlag>::type>(flag)) { + legacy_bucket_spec.report_events |= + convertHidlGscanReportEventFlagToLegacy(flag); + } + } + if (hidl_bucket_spec.frequencies.size() > MAX_CHANNELS) { + return false; + } + legacy_bucket_spec.num_channels = hidl_bucket_spec.frequencies.size(); + for (uint32_t freq_idx = 0; + freq_idx < hidl_bucket_spec.frequencies.size(); freq_idx++) { + legacy_bucket_spec.channels[freq_idx].channel = + hidl_bucket_spec.frequencies[freq_idx]; + } + } + return true; +} + +bool convertLegacyIeToHidl( + const legacy_hal::wifi_information_element& legacy_ie, + WifiInformationElement* hidl_ie) { + if (!hidl_ie) { + return false; + } + *hidl_ie = {}; + hidl_ie->id = legacy_ie.id; + hidl_ie->data = + std::vector<uint8_t>(legacy_ie.data, legacy_ie.data + legacy_ie.len); + return true; +} + +bool convertLegacyIeBlobToHidl(const uint8_t* ie_blob, uint32_t ie_blob_len, + std::vector<WifiInformationElement>* hidl_ies) { + if (!ie_blob || !hidl_ies) { + return false; + } + *hidl_ies = {}; + const uint8_t* ies_begin = ie_blob; + const uint8_t* ies_end = ie_blob + ie_blob_len; + const uint8_t* next_ie = ies_begin; + using wifi_ie = legacy_hal::wifi_information_element; + constexpr size_t kIeHeaderLen = sizeof(wifi_ie); + // Each IE should atleast have the header (i.e |id| & |len| fields). + while (next_ie + kIeHeaderLen <= ies_end) { + const wifi_ie& legacy_ie = (*reinterpret_cast<const wifi_ie*>(next_ie)); + uint32_t curr_ie_len = kIeHeaderLen + legacy_ie.len; + if (next_ie + curr_ie_len > ies_end) { + LOG(ERROR) << "Error parsing IE blob. Next IE: " << (void*)next_ie + << ", Curr IE len: " << curr_ie_len + << ", IEs End: " << (void*)ies_end; + break; + } + WifiInformationElement hidl_ie; + if (!convertLegacyIeToHidl(legacy_ie, &hidl_ie)) { + LOG(ERROR) << "Error converting IE. Id: " << legacy_ie.id + << ", len: " << legacy_ie.len; + break; + } + hidl_ies->push_back(std::move(hidl_ie)); + next_ie += curr_ie_len; + } + // Check if the blob has been fully consumed. + if (next_ie != ies_end) { + LOG(ERROR) << "Failed to fully parse IE blob. Next IE: " + << (void*)next_ie << ", IEs End: " << (void*)ies_end; + } + return true; +} + +bool convertLegacyGscanResultToHidl( + const legacy_hal::wifi_scan_result& legacy_scan_result, bool has_ie_data, + StaScanResult* hidl_scan_result) { + if (!hidl_scan_result) { + return false; + } + *hidl_scan_result = {}; + hidl_scan_result->timeStampInUs = legacy_scan_result.ts; + hidl_scan_result->ssid = std::vector<uint8_t>( + legacy_scan_result.ssid, + legacy_scan_result.ssid + strnlen(legacy_scan_result.ssid, + sizeof(legacy_scan_result.ssid) - 1)); + memcpy(hidl_scan_result->bssid.data(), legacy_scan_result.bssid, + hidl_scan_result->bssid.size()); + hidl_scan_result->frequency = legacy_scan_result.channel; + hidl_scan_result->rssi = legacy_scan_result.rssi; + hidl_scan_result->beaconPeriodInMs = legacy_scan_result.beacon_period; + hidl_scan_result->capability = legacy_scan_result.capability; + if (has_ie_data) { + std::vector<WifiInformationElement> ies; + if (!convertLegacyIeBlobToHidl( + reinterpret_cast<const uint8_t*>(legacy_scan_result.ie_data), + legacy_scan_result.ie_length, &ies)) { + return false; + } + hidl_scan_result->informationElements = std::move(ies); + } + return true; +} + +bool convertLegacyCachedGscanResultsToHidl( + const legacy_hal::wifi_cached_scan_results& legacy_cached_scan_result, + StaScanData* hidl_scan_data) { + if (!hidl_scan_data) { + return false; + } + *hidl_scan_data = {}; + hidl_scan_data->flags = 0; + for (const auto flag : {legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED}) { + if (legacy_cached_scan_result.flags & flag) { + hidl_scan_data->flags |= + static_cast<std::underlying_type<StaScanDataFlagMask>::type>( + convertLegacyGscanDataFlagToHidl(flag)); + } + } + hidl_scan_data->bucketsScanned = legacy_cached_scan_result.buckets_scanned; + + CHECK(legacy_cached_scan_result.num_results >= 0 && + legacy_cached_scan_result.num_results <= MAX_AP_CACHE_PER_SCAN); + std::vector<StaScanResult> hidl_scan_results; + for (int32_t result_idx = 0; + result_idx < legacy_cached_scan_result.num_results; result_idx++) { + StaScanResult hidl_scan_result; + if (!convertLegacyGscanResultToHidl( + legacy_cached_scan_result.results[result_idx], false, + &hidl_scan_result)) { + return false; + } + hidl_scan_results.push_back(hidl_scan_result); + } + hidl_scan_data->results = std::move(hidl_scan_results); + return true; +} + +bool convertLegacyVectorOfCachedGscanResultsToHidl( + const std::vector<legacy_hal::wifi_cached_scan_results>& + legacy_cached_scan_results, + std::vector<StaScanData>* hidl_scan_datas) { + if (!hidl_scan_datas) { + return false; + } + *hidl_scan_datas = {}; + for (const auto& legacy_cached_scan_result : legacy_cached_scan_results) { + StaScanData hidl_scan_data; + if (!convertLegacyCachedGscanResultsToHidl(legacy_cached_scan_result, + &hidl_scan_data)) { + return false; + } + hidl_scan_datas->push_back(hidl_scan_data); + } + return true; +} + +WifiDebugTxPacketFate convertLegacyDebugTxPacketFateToHidl( + legacy_hal::wifi_tx_packet_fate fate) { + switch (fate) { + case legacy_hal::TX_PKT_FATE_ACKED: + return WifiDebugTxPacketFate::ACKED; + case legacy_hal::TX_PKT_FATE_SENT: + return WifiDebugTxPacketFate::SENT; + case legacy_hal::TX_PKT_FATE_FW_QUEUED: + return WifiDebugTxPacketFate::FW_QUEUED; + case legacy_hal::TX_PKT_FATE_FW_DROP_INVALID: + return WifiDebugTxPacketFate::FW_DROP_INVALID; + case legacy_hal::TX_PKT_FATE_FW_DROP_NOBUFS: + return WifiDebugTxPacketFate::FW_DROP_NOBUFS; + case legacy_hal::TX_PKT_FATE_FW_DROP_OTHER: + return WifiDebugTxPacketFate::FW_DROP_OTHER; + case legacy_hal::TX_PKT_FATE_DRV_QUEUED: + return WifiDebugTxPacketFate::DRV_QUEUED; + case legacy_hal::TX_PKT_FATE_DRV_DROP_INVALID: + return WifiDebugTxPacketFate::DRV_DROP_INVALID; + case legacy_hal::TX_PKT_FATE_DRV_DROP_NOBUFS: + return WifiDebugTxPacketFate::DRV_DROP_NOBUFS; + case legacy_hal::TX_PKT_FATE_DRV_DROP_OTHER: + return WifiDebugTxPacketFate::DRV_DROP_OTHER; + }; + CHECK(false) << "Unknown legacy fate type: " << fate; +} + +WifiDebugRxPacketFate convertLegacyDebugRxPacketFateToHidl( + legacy_hal::wifi_rx_packet_fate fate) { + switch (fate) { + case legacy_hal::RX_PKT_FATE_SUCCESS: + return WifiDebugRxPacketFate::SUCCESS; + case legacy_hal::RX_PKT_FATE_FW_QUEUED: + return WifiDebugRxPacketFate::FW_QUEUED; + case legacy_hal::RX_PKT_FATE_FW_DROP_FILTER: + return WifiDebugRxPacketFate::FW_DROP_FILTER; + case legacy_hal::RX_PKT_FATE_FW_DROP_INVALID: + return WifiDebugRxPacketFate::FW_DROP_INVALID; + case legacy_hal::RX_PKT_FATE_FW_DROP_NOBUFS: + return WifiDebugRxPacketFate::FW_DROP_NOBUFS; + case legacy_hal::RX_PKT_FATE_FW_DROP_OTHER: + return WifiDebugRxPacketFate::FW_DROP_OTHER; + case legacy_hal::RX_PKT_FATE_DRV_QUEUED: + return WifiDebugRxPacketFate::DRV_QUEUED; + case legacy_hal::RX_PKT_FATE_DRV_DROP_FILTER: + return WifiDebugRxPacketFate::DRV_DROP_FILTER; + case legacy_hal::RX_PKT_FATE_DRV_DROP_INVALID: + return WifiDebugRxPacketFate::DRV_DROP_INVALID; + case legacy_hal::RX_PKT_FATE_DRV_DROP_NOBUFS: + return WifiDebugRxPacketFate::DRV_DROP_NOBUFS; + case legacy_hal::RX_PKT_FATE_DRV_DROP_OTHER: + return WifiDebugRxPacketFate::DRV_DROP_OTHER; + }; + CHECK(false) << "Unknown legacy fate type: " << fate; +} + +WifiDebugPacketFateFrameType convertLegacyDebugPacketFateFrameTypeToHidl( + legacy_hal::frame_type type) { + switch (type) { + case legacy_hal::FRAME_TYPE_UNKNOWN: + return WifiDebugPacketFateFrameType::UNKNOWN; + case legacy_hal::FRAME_TYPE_ETHERNET_II: + return WifiDebugPacketFateFrameType::ETHERNET_II; + case legacy_hal::FRAME_TYPE_80211_MGMT: + return WifiDebugPacketFateFrameType::MGMT_80211; + }; + CHECK(false) << "Unknown legacy frame type: " << type; +} + +bool convertLegacyDebugPacketFateFrameToHidl( + const legacy_hal::frame_info& legacy_frame, + WifiDebugPacketFateFrameInfo* hidl_frame) { + if (!hidl_frame) { + return false; + } + *hidl_frame = {}; + hidl_frame->frameType = + convertLegacyDebugPacketFateFrameTypeToHidl(legacy_frame.payload_type); + hidl_frame->frameLen = legacy_frame.frame_len; + hidl_frame->driverTimestampUsec = legacy_frame.driver_timestamp_usec; + hidl_frame->firmwareTimestampUsec = legacy_frame.firmware_timestamp_usec; + const uint8_t* frame_begin = reinterpret_cast<const uint8_t*>( + legacy_frame.frame_content.ethernet_ii_bytes); + hidl_frame->frameContent = + std::vector<uint8_t>(frame_begin, frame_begin + legacy_frame.frame_len); + return true; +} + +bool convertLegacyDebugTxPacketFateToHidl( + const legacy_hal::wifi_tx_report& legacy_fate, + WifiDebugTxPacketFateReport* hidl_fate) { + if (!hidl_fate) { + return false; + } + *hidl_fate = {}; + hidl_fate->fate = convertLegacyDebugTxPacketFateToHidl(legacy_fate.fate); + return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf, + &hidl_fate->frameInfo); +} + +bool convertLegacyVectorOfDebugTxPacketFateToHidl( + const std::vector<legacy_hal::wifi_tx_report>& legacy_fates, + std::vector<WifiDebugTxPacketFateReport>* hidl_fates) { + if (!hidl_fates) { + return false; + } + *hidl_fates = {}; + for (const auto& legacy_fate : legacy_fates) { + WifiDebugTxPacketFateReport hidl_fate; + if (!convertLegacyDebugTxPacketFateToHidl(legacy_fate, &hidl_fate)) { + return false; + } + hidl_fates->push_back(hidl_fate); + } + return true; +} + +bool convertLegacyDebugRxPacketFateToHidl( + const legacy_hal::wifi_rx_report& legacy_fate, + WifiDebugRxPacketFateReport* hidl_fate) { + if (!hidl_fate) { + return false; + } + *hidl_fate = {}; + hidl_fate->fate = convertLegacyDebugRxPacketFateToHidl(legacy_fate.fate); + return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf, + &hidl_fate->frameInfo); +} + +bool convertLegacyVectorOfDebugRxPacketFateToHidl( + const std::vector<legacy_hal::wifi_rx_report>& legacy_fates, + std::vector<WifiDebugRxPacketFateReport>* hidl_fates) { + if (!hidl_fates) { + return false; + } + *hidl_fates = {}; + for (const auto& legacy_fate : legacy_fates) { + WifiDebugRxPacketFateReport hidl_fate; + if (!convertLegacyDebugRxPacketFateToHidl(legacy_fate, &hidl_fate)) { + return false; + } + hidl_fates->push_back(hidl_fate); + } + return true; +} + +bool convertLegacyLinkLayerRadioStatsToHidl( + const legacy_hal::LinkLayerRadioStats& legacy_radio_stat, + V1_3::StaLinkLayerRadioStats* hidl_radio_stat) { + if (!hidl_radio_stat) { + return false; + } + *hidl_radio_stat = {}; + + hidl_radio_stat->V1_0.onTimeInMs = legacy_radio_stat.stats.on_time; + hidl_radio_stat->V1_0.txTimeInMs = legacy_radio_stat.stats.tx_time; + hidl_radio_stat->V1_0.rxTimeInMs = legacy_radio_stat.stats.rx_time; + hidl_radio_stat->V1_0.onTimeInMsForScan = + legacy_radio_stat.stats.on_time_scan; + hidl_radio_stat->V1_0.txTimeInMsPerLevel = + legacy_radio_stat.tx_time_per_levels; + hidl_radio_stat->onTimeInMsForNanScan = legacy_radio_stat.stats.on_time_nbd; + hidl_radio_stat->onTimeInMsForBgScan = + legacy_radio_stat.stats.on_time_gscan; + hidl_radio_stat->onTimeInMsForRoamScan = + legacy_radio_stat.stats.on_time_roam_scan; + hidl_radio_stat->onTimeInMsForPnoScan = + legacy_radio_stat.stats.on_time_pno_scan; + hidl_radio_stat->onTimeInMsForHs20Scan = + legacy_radio_stat.stats.on_time_hs20; + + std::vector<V1_3::WifiChannelStats> hidl_channel_stats; + + for (const auto& channel_stat : legacy_radio_stat.channel_stats) { + V1_3::WifiChannelStats hidl_channel_stat; + hidl_channel_stat.onTimeInMs = channel_stat.on_time; + hidl_channel_stat.ccaBusyTimeInMs = channel_stat.cca_busy_time; + /* + * TODO once b/119142899 is fixed, + * replace below code with convertLegacyWifiChannelInfoToHidl() + */ + hidl_channel_stat.channel.width = WifiChannelWidthInMhz::WIDTH_20; + hidl_channel_stat.channel.centerFreq = channel_stat.channel.center_freq; + hidl_channel_stat.channel.centerFreq0 = + channel_stat.channel.center_freq0; + hidl_channel_stat.channel.centerFreq1 = + channel_stat.channel.center_freq1; + hidl_channel_stats.push_back(hidl_channel_stat); + } + + hidl_radio_stat->channelStats = hidl_channel_stats; + + return true; +} + +bool convertLegacyLinkLayerStatsToHidl( + const legacy_hal::LinkLayerStats& legacy_stats, + V1_3::StaLinkLayerStats* hidl_stats) { + if (!hidl_stats) { + return false; + } + *hidl_stats = {}; + // iface legacy_stats conversion. + hidl_stats->iface.beaconRx = legacy_stats.iface.beacon_rx; + hidl_stats->iface.avgRssiMgmt = legacy_stats.iface.rssi_mgmt; + hidl_stats->iface.wmeBePktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu; + hidl_stats->iface.wmeBePktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu; + hidl_stats->iface.wmeBePktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost; + hidl_stats->iface.wmeBePktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries; + hidl_stats->iface.wmeBkPktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu; + hidl_stats->iface.wmeBkPktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu; + hidl_stats->iface.wmeBkPktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost; + hidl_stats->iface.wmeBkPktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries; + hidl_stats->iface.wmeViPktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu; + hidl_stats->iface.wmeViPktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu; + hidl_stats->iface.wmeViPktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost; + hidl_stats->iface.wmeViPktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries; + hidl_stats->iface.wmeVoPktStats.rxMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu; + hidl_stats->iface.wmeVoPktStats.txMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu; + hidl_stats->iface.wmeVoPktStats.lostMpdu = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost; + hidl_stats->iface.wmeVoPktStats.retries = + legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries; + // radio legacy_stats conversion. + std::vector<V1_3::StaLinkLayerRadioStats> hidl_radios_stats; + for (const auto& legacy_radio_stats : legacy_stats.radios) { + V1_3::StaLinkLayerRadioStats hidl_radio_stats; + if (!convertLegacyLinkLayerRadioStatsToHidl(legacy_radio_stats, + &hidl_radio_stats)) { + return false; + } + hidl_radios_stats.push_back(hidl_radio_stats); + } + hidl_stats->radios = hidl_radios_stats; + // Timestamp in the HAL wrapper here since it's not provided in the legacy + // HAL API. + hidl_stats->timeStampInMs = uptimeMillis(); + return true; +} + +bool convertLegacyRoamingCapabilitiesToHidl( + const legacy_hal::wifi_roaming_capabilities& legacy_caps, + StaRoamingCapabilities* hidl_caps) { + if (!hidl_caps) { + return false; + } + *hidl_caps = {}; + hidl_caps->maxBlacklistSize = legacy_caps.max_blacklist_size; + hidl_caps->maxWhitelistSize = legacy_caps.max_whitelist_size; + return true; +} + +bool convertHidlRoamingConfigToLegacy( + const StaRoamingConfig& hidl_config, + legacy_hal::wifi_roaming_config* legacy_config) { + if (!legacy_config) { + return false; + } + *legacy_config = {}; + if (hidl_config.bssidBlacklist.size() > MAX_BLACKLIST_BSSID || + hidl_config.ssidWhitelist.size() > MAX_WHITELIST_SSID) { + return false; + } + legacy_config->num_blacklist_bssid = hidl_config.bssidBlacklist.size(); + uint32_t i = 0; + for (const auto& bssid : hidl_config.bssidBlacklist) { + CHECK(bssid.size() == sizeof(legacy_hal::mac_addr)); + memcpy(legacy_config->blacklist_bssid[i++], bssid.data(), bssid.size()); + } + legacy_config->num_whitelist_ssid = hidl_config.ssidWhitelist.size(); + i = 0; + for (const auto& ssid : hidl_config.ssidWhitelist) { + CHECK(ssid.size() <= sizeof(legacy_hal::ssid_t::ssid_str)); + legacy_config->whitelist_ssid[i].length = ssid.size(); + memcpy(legacy_config->whitelist_ssid[i].ssid_str, ssid.data(), + ssid.size()); + i++; + } + return true; +} + +legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy( + StaRoamingState state) { + switch (state) { + case StaRoamingState::ENABLED: + return legacy_hal::ROAMING_ENABLE; + case StaRoamingState::DISABLED: + return legacy_hal::ROAMING_DISABLE; + }; + CHECK(false); +} + +legacy_hal::NanMatchAlg convertHidlNanMatchAlgToLegacy(NanMatchAlg type) { + switch (type) { + case NanMatchAlg::MATCH_ONCE: + return legacy_hal::NAN_MATCH_ALG_MATCH_ONCE; + case NanMatchAlg::MATCH_CONTINUOUS: + return legacy_hal::NAN_MATCH_ALG_MATCH_CONTINUOUS; + case NanMatchAlg::MATCH_NEVER: + return legacy_hal::NAN_MATCH_ALG_MATCH_NEVER; + } + CHECK(false); +} + +legacy_hal::NanPublishType convertHidlNanPublishTypeToLegacy( + NanPublishType type) { + switch (type) { + case NanPublishType::UNSOLICITED: + return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED; + case NanPublishType::SOLICITED: + return legacy_hal::NAN_PUBLISH_TYPE_SOLICITED; + case NanPublishType::UNSOLICITED_SOLICITED: + return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED; + } + CHECK(false); +} + +legacy_hal::NanTxType convertHidlNanTxTypeToLegacy(NanTxType type) { + switch (type) { + case NanTxType::BROADCAST: + return legacy_hal::NAN_TX_TYPE_BROADCAST; + case NanTxType::UNICAST: + return legacy_hal::NAN_TX_TYPE_UNICAST; + } + CHECK(false); +} + +legacy_hal::NanSubscribeType convertHidlNanSubscribeTypeToLegacy( + NanSubscribeType type) { + switch (type) { + case NanSubscribeType::PASSIVE: + return legacy_hal::NAN_SUBSCRIBE_TYPE_PASSIVE; + case NanSubscribeType::ACTIVE: + return legacy_hal::NAN_SUBSCRIBE_TYPE_ACTIVE; + } + CHECK(false); +} + +legacy_hal::NanSRFType convertHidlNanSrfTypeToLegacy(NanSrfType type) { + switch (type) { + case NanSrfType::BLOOM_FILTER: + return legacy_hal::NAN_SRF_ATTR_BLOOM_FILTER; + case NanSrfType::PARTIAL_MAC_ADDR: + return legacy_hal::NAN_SRF_ATTR_PARTIAL_MAC_ADDR; + } + CHECK(false); +} + +legacy_hal::NanDataPathChannelCfg convertHidlNanDataPathChannelCfgToLegacy( + NanDataPathChannelCfg type) { + switch (type) { + case NanDataPathChannelCfg::CHANNEL_NOT_REQUESTED: + return legacy_hal::NAN_DP_CHANNEL_NOT_REQUESTED; + case NanDataPathChannelCfg::REQUEST_CHANNEL_SETUP: + return legacy_hal::NAN_DP_REQUEST_CHANNEL_SETUP; + case NanDataPathChannelCfg::FORCE_CHANNEL_SETUP: + return legacy_hal::NAN_DP_FORCE_CHANNEL_SETUP; + } + CHECK(false); +} + +NanStatusType convertLegacyNanStatusTypeToHidl(legacy_hal::NanStatusType type) { + switch (type) { + case legacy_hal::NAN_STATUS_SUCCESS: + return NanStatusType::SUCCESS; + case legacy_hal::NAN_STATUS_INTERNAL_FAILURE: + return NanStatusType::INTERNAL_FAILURE; + case legacy_hal::NAN_STATUS_PROTOCOL_FAILURE: + return NanStatusType::PROTOCOL_FAILURE; + case legacy_hal::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID: + return NanStatusType::INVALID_SESSION_ID; + case legacy_hal::NAN_STATUS_NO_RESOURCE_AVAILABLE: + return NanStatusType::NO_RESOURCES_AVAILABLE; + case legacy_hal::NAN_STATUS_INVALID_PARAM: + return NanStatusType::INVALID_ARGS; + case legacy_hal::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID: + return NanStatusType::INVALID_PEER_ID; + case legacy_hal::NAN_STATUS_INVALID_NDP_ID: + return NanStatusType::INVALID_NDP_ID; + case legacy_hal::NAN_STATUS_NAN_NOT_ALLOWED: + return NanStatusType::NAN_NOT_ALLOWED; + case legacy_hal::NAN_STATUS_NO_OTA_ACK: + return NanStatusType::NO_OTA_ACK; + case legacy_hal::NAN_STATUS_ALREADY_ENABLED: + return NanStatusType::ALREADY_ENABLED; + case legacy_hal::NAN_STATUS_FOLLOWUP_QUEUE_FULL: + return NanStatusType::FOLLOWUP_TX_QUEUE_FULL; + case legacy_hal::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED: + return NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED; + } + CHECK(false); +} + +void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, + size_t max_len, WifiNanStatus* wifiNanStatus) { + wifiNanStatus->status = convertLegacyNanStatusTypeToHidl(type); + wifiNanStatus->description = safeConvertChar(str, max_len); +} + +bool convertHidlNanEnableRequestToLegacy( + const NanEnableRequest& hidl_request, + legacy_hal::NanEnableRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) + << "convertHidlNanEnableRequestToLegacy: null legacy_request"; + return false; + } + *legacy_request = {}; + + legacy_request->config_2dot4g_support = 1; + legacy_request->support_2dot4g_val = + hidl_request.operateInBand[(size_t)NanBandIndex::NAN_BAND_24GHZ]; + legacy_request->config_support_5g = 1; + legacy_request->support_5g_val = + hidl_request.operateInBand[(size_t)NanBandIndex::NAN_BAND_5GHZ]; + legacy_request->config_hop_count_limit = 1; + legacy_request->hop_count_limit_val = hidl_request.hopCountMax; + legacy_request->master_pref = hidl_request.configParams.masterPref; + legacy_request->discovery_indication_cfg = 0; + legacy_request->discovery_indication_cfg |= + hidl_request.configParams.disableDiscoveryAddressChangeIndication ? 0x1 + : 0x0; + legacy_request->discovery_indication_cfg |= + hidl_request.configParams.disableStartedClusterIndication ? 0x2 : 0x0; + legacy_request->discovery_indication_cfg |= + hidl_request.configParams.disableJoinedClusterIndication ? 0x4 : 0x0; + legacy_request->config_sid_beacon = 1; + if (hidl_request.configParams.numberOfPublishServiceIdsInBeacon > 127) { + LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: " + "numberOfPublishServiceIdsInBeacon > 127"; + return false; + } + legacy_request->sid_beacon_val = + (hidl_request.configParams.includePublishServiceIdsInBeacon ? 0x1 + : 0x0) | + (hidl_request.configParams.numberOfPublishServiceIdsInBeacon << 1); + legacy_request->config_subscribe_sid_beacon = 1; + if (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon > 127) { + LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: " + "numberOfSubscribeServiceIdsInBeacon > 127"; + return false; + } + legacy_request->subscribe_sid_beacon_val = + (hidl_request.configParams.includeSubscribeServiceIdsInBeacon ? 0x1 + : 0x0) | + (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon << 1); + legacy_request->config_rssi_window_size = 1; + legacy_request->rssi_window_size_val = + hidl_request.configParams.rssiWindowSize; + legacy_request->config_disc_mac_addr_randomization = 1; + legacy_request->disc_mac_addr_rand_interval_sec = + hidl_request.configParams.macAddressRandomizationIntervalSec; + legacy_request->config_2dot4g_rssi_close = 1; + if (hidl_request.configParams.bandSpecificConfig.size() != 2) { + LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: " + "bandSpecificConfig.size() != 2"; + return false; + } + legacy_request->rssi_close_2dot4g_val = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .rssiClose; + legacy_request->config_2dot4g_rssi_middle = 1; + legacy_request->rssi_middle_2dot4g_val = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .rssiMiddle; + legacy_request->config_2dot4g_rssi_proximity = 1; + legacy_request->rssi_proximity_2dot4g_val = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .rssiCloseProximity; + legacy_request->config_scan_params = 1; + legacy_request->scan_params_val + .dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .dwellTimeMs; + legacy_request->scan_params_val + .scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .scanPeriodSec; + legacy_request->config_dw.config_2dot4g_dw_band = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .validDiscoveryWindowIntervalVal; + legacy_request->config_dw.dw_2dot4g_interval_val = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .discoveryWindowIntervalVal; + legacy_request->config_5g_rssi_close = 1; + legacy_request->rssi_close_5g_val = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .rssiClose; + legacy_request->config_5g_rssi_middle = 1; + legacy_request->rssi_middle_5g_val = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .rssiMiddle; + legacy_request->config_5g_rssi_close_proximity = 1; + legacy_request->rssi_close_proximity_5g_val = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .rssiCloseProximity; + legacy_request->scan_params_val + .dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .dwellTimeMs; + legacy_request->scan_params_val + .scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .scanPeriodSec; + legacy_request->scan_params_val + .dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .dwellTimeMs; + legacy_request->scan_params_val + .scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .scanPeriodSec; + legacy_request->config_dw.config_5g_dw_band = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .validDiscoveryWindowIntervalVal; + legacy_request->config_dw.dw_5g_interval_val = + hidl_request.configParams + .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .discoveryWindowIntervalVal; + if (hidl_request.debugConfigs.validClusterIdVals) { + legacy_request->cluster_low = + hidl_request.debugConfigs.clusterIdBottomRangeVal; + legacy_request->cluster_high = + hidl_request.debugConfigs.clusterIdTopRangeVal; + } else { // need 'else' since not configurable in legacy HAL + legacy_request->cluster_low = 0x0000; + legacy_request->cluster_high = 0xFFFF; + } + legacy_request->config_intf_addr = + hidl_request.debugConfigs.validIntfAddrVal; + memcpy(legacy_request->intf_addr_val, + hidl_request.debugConfigs.intfAddrVal.data(), 6); + legacy_request->config_oui = hidl_request.debugConfigs.validOuiVal; + legacy_request->oui_val = hidl_request.debugConfigs.ouiVal; + legacy_request->config_random_factor_force = + hidl_request.debugConfigs.validRandomFactorForceVal; + legacy_request->random_factor_force_val = + hidl_request.debugConfigs.randomFactorForceVal; + legacy_request->config_hop_count_force = + hidl_request.debugConfigs.validHopCountForceVal; + legacy_request->hop_count_force_val = + hidl_request.debugConfigs.hopCountForceVal; + legacy_request->config_24g_channel = + hidl_request.debugConfigs.validDiscoveryChannelVal; + legacy_request->channel_24g_val = + hidl_request.debugConfigs + .discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_24GHZ]; + legacy_request->config_5g_channel = + hidl_request.debugConfigs.validDiscoveryChannelVal; + legacy_request->channel_5g_val = + hidl_request.debugConfigs + .discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_5GHZ]; + legacy_request->config_2dot4g_beacons = + hidl_request.debugConfigs.validUseBeaconsInBandVal; + legacy_request->beacon_2dot4g_val = + hidl_request.debugConfigs + .useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ]; + legacy_request->config_5g_beacons = + hidl_request.debugConfigs.validUseBeaconsInBandVal; + legacy_request->beacon_5g_val = + hidl_request.debugConfigs + .useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ]; + legacy_request->config_2dot4g_sdf = + hidl_request.debugConfigs.validUseSdfInBandVal; + legacy_request->sdf_2dot4g_val = + hidl_request.debugConfigs + .useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ]; + legacy_request->config_5g_sdf = + hidl_request.debugConfigs.validUseSdfInBandVal; + legacy_request->sdf_5g_val = + hidl_request.debugConfigs + .useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ]; + + return true; +} + +bool convertHidlNanEnableRequest_1_2ToLegacy( + const NanEnableRequest& hidl_request1, + const V1_2::NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanEnableRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) + << "convertHidlNanEnableRequest_1_2ToLegacy: null legacy_request"; + return false; + } + + *legacy_request = {}; + if (!convertHidlNanEnableRequestToLegacy(hidl_request1, legacy_request)) { + return false; + } + + legacy_request->config_discovery_beacon_int = 1; + legacy_request->discovery_beacon_interval = + hidl_request2.discoveryBeaconIntervalMs; + legacy_request->config_nss = 1; + legacy_request->nss = hidl_request2.numberOfSpatialStreamsInDiscovery; + legacy_request->config_dw_early_termination = 1; + legacy_request->enable_dw_termination = + hidl_request2.enableDiscoveryWindowEarlyTermination; + legacy_request->config_enable_ranging = 1; + legacy_request->enable_ranging = hidl_request2.enableRanging; + + return true; +} + +bool convertHidlNanPublishRequestToLegacy( + const NanPublishRequest& hidl_request, + legacy_hal::NanPublishRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) + << "convertHidlNanPublishRequestToLegacy: null legacy_request"; + return false; + } + *legacy_request = {}; + + legacy_request->publish_id = hidl_request.baseConfigs.sessionId; + legacy_request->ttl = hidl_request.baseConfigs.ttlSec; + legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod; + legacy_request->publish_count = hidl_request.baseConfigs.discoveryCount; + legacy_request->service_name_len = + hidl_request.baseConfigs.serviceName.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: service_name_len " + "too large"; + return false; + } + memcpy(legacy_request->service_name, + hidl_request.baseConfigs.serviceName.data(), + legacy_request->service_name_len); + legacy_request->publish_match_indicator = convertHidlNanMatchAlgToLegacy( + hidl_request.baseConfigs.discoveryMatchIndicator); + legacy_request->service_specific_info_len = + hidl_request.baseConfigs.serviceSpecificInfo.size(); + if (legacy_request->service_specific_info_len > + NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: " + "service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->service_specific_info, + hidl_request.baseConfigs.serviceSpecificInfo.data(), + legacy_request->service_specific_info_len); + legacy_request->sdea_service_specific_info_len = + hidl_request.baseConfigs.extendedServiceSpecificInfo.size(); + if (legacy_request->sdea_service_specific_info_len > + NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: " + "sdea_service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->sdea_service_specific_info, + hidl_request.baseConfigs.extendedServiceSpecificInfo.data(), + legacy_request->sdea_service_specific_info_len); + legacy_request->rx_match_filter_len = + hidl_request.baseConfigs.rxMatchFilter.size(); + if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: " + "rx_match_filter_len too large"; + return false; + } + memcpy(legacy_request->rx_match_filter, + hidl_request.baseConfigs.rxMatchFilter.data(), + legacy_request->rx_match_filter_len); + legacy_request->tx_match_filter_len = + hidl_request.baseConfigs.txMatchFilter.size(); + if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: " + "tx_match_filter_len too large"; + return false; + } + memcpy(legacy_request->tx_match_filter, + hidl_request.baseConfigs.txMatchFilter.data(), + legacy_request->tx_match_filter_len); + legacy_request->rssi_threshold_flag = + hidl_request.baseConfigs.useRssiThreshold; + legacy_request->recv_indication_cfg = 0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 + : 0x0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0; + legacy_request->recv_indication_cfg |= 0x8; + legacy_request->cipher_type = + (unsigned int)hidl_request.baseConfigs.securityConfig.cipherType; + if (hidl_request.baseConfigs.securityConfig.securityType == + NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = + legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = + hidl_request.baseConfigs.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != + NAN_PMK_INFO_LEN) { + LOG(ERROR) + << "convertHidlNanPublishRequestToLegacy: invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, + hidl_request.baseConfigs.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.baseConfigs.securityConfig.securityType == + NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = + legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.baseConfigs.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len < + NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: " + "passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len > + NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: " + "passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.baseConfigs.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->sdea_params.security_cfg = + (hidl_request.baseConfigs.securityConfig.securityType != + NanDataPathSecurityType::OPEN) + ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->sdea_params.ranging_state = + hidl_request.baseConfigs.rangingRequired + ? legacy_hal::NAN_RANGING_ENABLE + : legacy_hal::NAN_RANGING_DISABLE; + legacy_request->ranging_cfg.ranging_interval_msec = + hidl_request.baseConfigs.rangingIntervalMsec; + legacy_request->ranging_cfg.config_ranging_indications = + hidl_request.baseConfigs.configRangingIndications; + legacy_request->ranging_cfg.distance_ingress_mm = + hidl_request.baseConfigs.distanceIngressCm * 10; + legacy_request->ranging_cfg.distance_egress_mm = + hidl_request.baseConfigs.distanceEgressCm * 10; + legacy_request->ranging_auto_response = + hidl_request.baseConfigs.rangingRequired + ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE + : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE; + legacy_request->sdea_params.range_report = + legacy_hal::NAN_DISABLE_RANGE_REPORT; + legacy_request->publish_type = + convertHidlNanPublishTypeToLegacy(hidl_request.publishType); + legacy_request->tx_type = convertHidlNanTxTypeToLegacy(hidl_request.txType); + legacy_request->service_responder_policy = + hidl_request.autoAcceptDataPathRequests + ? legacy_hal::NAN_SERVICE_ACCEPT_POLICY_ALL + : legacy_hal::NAN_SERVICE_ACCEPT_POLICY_NONE; + + return true; +} + +bool convertHidlNanSubscribeRequestToLegacy( + const NanSubscribeRequest& hidl_request, + legacy_hal::NanSubscribeRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) + << "convertHidlNanSubscribeRequestToLegacy: legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->subscribe_id = hidl_request.baseConfigs.sessionId; + legacy_request->ttl = hidl_request.baseConfigs.ttlSec; + legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod; + legacy_request->subscribe_count = hidl_request.baseConfigs.discoveryCount; + legacy_request->service_name_len = + hidl_request.baseConfigs.serviceName.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, + hidl_request.baseConfigs.serviceName.data(), + legacy_request->service_name_len); + legacy_request->subscribe_match_indicator = convertHidlNanMatchAlgToLegacy( + hidl_request.baseConfigs.discoveryMatchIndicator); + legacy_request->service_specific_info_len = + hidl_request.baseConfigs.serviceSpecificInfo.size(); + if (legacy_request->service_specific_info_len > + NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->service_specific_info, + hidl_request.baseConfigs.serviceSpecificInfo.data(), + legacy_request->service_specific_info_len); + legacy_request->sdea_service_specific_info_len = + hidl_request.baseConfigs.extendedServiceSpecificInfo.size(); + if (legacy_request->sdea_service_specific_info_len > + NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "sdea_service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->sdea_service_specific_info, + hidl_request.baseConfigs.extendedServiceSpecificInfo.data(), + legacy_request->sdea_service_specific_info_len); + legacy_request->rx_match_filter_len = + hidl_request.baseConfigs.rxMatchFilter.size(); + if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "rx_match_filter_len too large"; + return false; + } + memcpy(legacy_request->rx_match_filter, + hidl_request.baseConfigs.rxMatchFilter.data(), + legacy_request->rx_match_filter_len); + legacy_request->tx_match_filter_len = + hidl_request.baseConfigs.txMatchFilter.size(); + if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "tx_match_filter_len too large"; + return false; + } + memcpy(legacy_request->tx_match_filter, + hidl_request.baseConfigs.txMatchFilter.data(), + legacy_request->tx_match_filter_len); + legacy_request->rssi_threshold_flag = + hidl_request.baseConfigs.useRssiThreshold; + legacy_request->recv_indication_cfg = 0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 + : 0x0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0; + legacy_request->recv_indication_cfg |= + hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0; + legacy_request->cipher_type = + (unsigned int)hidl_request.baseConfigs.securityConfig.cipherType; + if (hidl_request.baseConfigs.securityConfig.securityType == + NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = + legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = + hidl_request.baseConfigs.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != + NAN_PMK_INFO_LEN) { + LOG(ERROR) + << "convertHidlNanSubscribeRequestToLegacy: invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, + hidl_request.baseConfigs.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.baseConfigs.securityConfig.securityType == + NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = + legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.baseConfigs.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len < + NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len > + NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.baseConfigs.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->sdea_params.security_cfg = + (hidl_request.baseConfigs.securityConfig.securityType != + NanDataPathSecurityType::OPEN) + ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->sdea_params.ranging_state = + hidl_request.baseConfigs.rangingRequired + ? legacy_hal::NAN_RANGING_ENABLE + : legacy_hal::NAN_RANGING_DISABLE; + legacy_request->ranging_cfg.ranging_interval_msec = + hidl_request.baseConfigs.rangingIntervalMsec; + legacy_request->ranging_cfg.config_ranging_indications = + hidl_request.baseConfigs.configRangingIndications; + legacy_request->ranging_cfg.distance_ingress_mm = + hidl_request.baseConfigs.distanceIngressCm * 10; + legacy_request->ranging_cfg.distance_egress_mm = + hidl_request.baseConfigs.distanceEgressCm * 10; + legacy_request->ranging_auto_response = + hidl_request.baseConfigs.rangingRequired + ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE + : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE; + legacy_request->sdea_params.range_report = + legacy_hal::NAN_DISABLE_RANGE_REPORT; + legacy_request->subscribe_type = + convertHidlNanSubscribeTypeToLegacy(hidl_request.subscribeType); + legacy_request->serviceResponseFilter = + convertHidlNanSrfTypeToLegacy(hidl_request.srfType); + legacy_request->serviceResponseInclude = + hidl_request.srfRespondIfInAddressSet + ? legacy_hal::NAN_SRF_INCLUDE_RESPOND + : legacy_hal::NAN_SRF_INCLUDE_DO_NOT_RESPOND; + legacy_request->useServiceResponseFilter = + hidl_request.shouldUseSrf ? legacy_hal::NAN_USE_SRF + : legacy_hal::NAN_DO_NOT_USE_SRF; + legacy_request->ssiRequiredForMatchIndication = + hidl_request.isSsiRequiredForMatch + ? legacy_hal::NAN_SSI_REQUIRED_IN_MATCH_IND + : legacy_hal::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND; + legacy_request->num_intf_addr_present = hidl_request.intfAddr.size(); + if (legacy_request->num_intf_addr_present > NAN_MAX_SUBSCRIBE_MAX_ADDRESS) { + LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: " + "num_intf_addr_present - too many"; + return false; + } + for (int i = 0; i < legacy_request->num_intf_addr_present; i++) { + memcpy(legacy_request->intf_addr[i], hidl_request.intfAddr[i].data(), + 6); + } + + return true; +} + +bool convertHidlNanTransmitFollowupRequestToLegacy( + const NanTransmitFollowupRequest& hidl_request, + legacy_hal::NanTransmitFollowupRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: " + "legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->publish_subscribe_id = hidl_request.discoverySessionId; + legacy_request->requestor_instance_id = hidl_request.peerId; + memcpy(legacy_request->addr, hidl_request.addr.data(), 6); + legacy_request->priority = hidl_request.isHighPriority + ? legacy_hal::NAN_TX_PRIORITY_HIGH + : legacy_hal::NAN_TX_PRIORITY_NORMAL; + legacy_request->dw_or_faw = hidl_request.shouldUseDiscoveryWindow + ? legacy_hal::NAN_TRANSMIT_IN_DW + : legacy_hal::NAN_TRANSMIT_IN_FAW; + legacy_request->service_specific_info_len = + hidl_request.serviceSpecificInfo.size(); + if (legacy_request->service_specific_info_len > + NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: " + "service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->service_specific_info, + hidl_request.serviceSpecificInfo.data(), + legacy_request->service_specific_info_len); + legacy_request->sdea_service_specific_info_len = + hidl_request.extendedServiceSpecificInfo.size(); + if (legacy_request->sdea_service_specific_info_len > + NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) { + LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: " + "sdea_service_specific_info_len too large"; + return false; + } + memcpy(legacy_request->sdea_service_specific_info, + hidl_request.extendedServiceSpecificInfo.data(), + legacy_request->sdea_service_specific_info_len); + legacy_request->recv_indication_cfg = + hidl_request.disableFollowupResultIndication ? 0x1 : 0x0; + + return true; +} + +bool convertHidlNanConfigRequestToLegacy( + const NanConfigRequest& hidl_request, + legacy_hal::NanConfigRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) + << "convertHidlNanConfigRequestToLegacy: legacy_request is null"; + return false; + } + *legacy_request = {}; + + // TODO: b/34059183 tracks missing configurations in legacy HAL or uknown + // defaults + legacy_request->master_pref = hidl_request.masterPref; + legacy_request->discovery_indication_cfg = 0; + legacy_request->discovery_indication_cfg |= + hidl_request.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0; + legacy_request->discovery_indication_cfg |= + hidl_request.disableStartedClusterIndication ? 0x2 : 0x0; + legacy_request->discovery_indication_cfg |= + hidl_request.disableJoinedClusterIndication ? 0x4 : 0x0; + legacy_request->config_sid_beacon = 1; + if (hidl_request.numberOfPublishServiceIdsInBeacon > 127) { + LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: " + "numberOfPublishServiceIdsInBeacon > 127"; + return false; + } + legacy_request->sid_beacon = + (hidl_request.includePublishServiceIdsInBeacon ? 0x1 : 0x0) | + (hidl_request.numberOfPublishServiceIdsInBeacon << 1); + legacy_request->config_subscribe_sid_beacon = 1; + if (hidl_request.numberOfSubscribeServiceIdsInBeacon > 127) { + LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: " + "numberOfSubscribeServiceIdsInBeacon > 127"; + return false; + } + legacy_request->subscribe_sid_beacon_val = + (hidl_request.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) | + (hidl_request.numberOfSubscribeServiceIdsInBeacon << 1); + legacy_request->config_rssi_window_size = 1; + legacy_request->rssi_window_size_val = hidl_request.rssiWindowSize; + legacy_request->config_disc_mac_addr_randomization = 1; + legacy_request->disc_mac_addr_rand_interval_sec = + hidl_request.macAddressRandomizationIntervalSec; + /* TODO : missing + legacy_request->config_2dot4g_rssi_close = 1; + legacy_request->rssi_close_2dot4g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiClose; + legacy_request->config_2dot4g_rssi_middle = 1; + legacy_request->rssi_middle_2dot4g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiMiddle; + legacy_request->config_2dot4g_rssi_proximity = 1; + legacy_request->rssi_proximity_2dot4g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiCloseProximity; + */ + legacy_request->config_scan_params = 1; + legacy_request->scan_params_val + .dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .dwellTimeMs; + legacy_request->scan_params_val + .scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .scanPeriodSec; + legacy_request->config_dw.config_2dot4g_dw_band = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .validDiscoveryWindowIntervalVal; + legacy_request->config_dw.dw_2dot4g_interval_val = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ] + .discoveryWindowIntervalVal; + /* TODO: missing + legacy_request->config_5g_rssi_close = 1; + legacy_request->rssi_close_5g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiClose; + legacy_request->config_5g_rssi_middle = 1; + legacy_request->rssi_middle_5g_val = + hidl_request.bandSpecificConfig[ + (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiMiddle; + */ + legacy_request->config_5g_rssi_close_proximity = 1; + legacy_request->rssi_close_proximity_5g_val = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .rssiCloseProximity; + legacy_request->scan_params_val + .dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .dwellTimeMs; + legacy_request->scan_params_val + .scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .scanPeriodSec; + legacy_request->scan_params_val + .dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .dwellTimeMs; + legacy_request->scan_params_val + .scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .scanPeriodSec; + legacy_request->config_dw.config_5g_dw_band = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .validDiscoveryWindowIntervalVal; + legacy_request->config_dw.dw_5g_interval_val = + hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ] + .discoveryWindowIntervalVal; + + return true; +} + +bool convertHidlNanConfigRequest_1_2ToLegacy( + const NanConfigRequest& hidl_request1, + const V1_2::NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanConfigRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanConfigRequest_1_2ToLegacy: legacy_request " + "is null"; + return false; + } + + *legacy_request = {}; + if (!convertHidlNanConfigRequestToLegacy(hidl_request1, legacy_request)) { + return false; + } + + legacy_request->config_discovery_beacon_int = 1; + legacy_request->discovery_beacon_interval = + hidl_request2.discoveryBeaconIntervalMs; + legacy_request->config_nss = 1; + legacy_request->nss = hidl_request2.numberOfSpatialStreamsInDiscovery; + legacy_request->config_dw_early_termination = 1; + legacy_request->enable_dw_termination = + hidl_request2.enableDiscoveryWindowEarlyTermination; + legacy_request->config_enable_ranging = 1; + legacy_request->enable_ranging = hidl_request2.enableRanging; + + return true; +} + +bool convertHidlNanDataPathInitiatorRequestToLegacy( + const NanInitiateDataPathRequest& hidl_request, + legacy_hal::NanDataPathInitiatorRequest* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->requestor_instance_id = hidl_request.peerId; + memcpy(legacy_request->peer_disc_mac_addr, + hidl_request.peerDiscMacAddr.data(), 6); + legacy_request->channel_request_type = + convertHidlNanDataPathChannelCfgToLegacy( + hidl_request.channelRequestType); + legacy_request->channel = hidl_request.channel; + strcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str()); + legacy_request->ndp_cfg.security_cfg = + (hidl_request.securityConfig.securityType != + NanDataPathSecurityType::OPEN) + ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size(); + if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "ndp_app_info_len too large"; + return false; + } + memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(), + legacy_request->app_info.ndp_app_info_len); + legacy_request->cipher_type = + (unsigned int)hidl_request.securityConfig.cipherType; + if (hidl_request.securityConfig.securityType == + NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = + legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = + hidl_request.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != + NAN_PMK_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, + hidl_request.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.securityConfig.securityType == + NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = + legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len < + NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len > + NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: " + "service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, + hidl_request.serviceNameOutOfBand.data(), + legacy_request->service_name_len); + + return true; +} + +bool convertHidlNanDataPathIndicationResponseToLegacy( + const NanRespondToDataPathIndicationRequest& hidl_request, + legacy_hal::NanDataPathIndicationResponse* legacy_request) { + if (!legacy_request) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "legacy_request is null"; + return false; + } + *legacy_request = {}; + + legacy_request->rsp_code = hidl_request.acceptRequest + ? legacy_hal::NAN_DP_REQUEST_ACCEPT + : legacy_hal::NAN_DP_REQUEST_REJECT; + legacy_request->ndp_instance_id = hidl_request.ndpInstanceId; + strcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str()); + legacy_request->ndp_cfg.security_cfg = + (hidl_request.securityConfig.securityType != + NanDataPathSecurityType::OPEN) + ? legacy_hal::NAN_DP_CONFIG_SECURITY + : legacy_hal::NAN_DP_CONFIG_NO_SECURITY; + legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size(); + if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "ndp_app_info_len too large"; + return false; + } + memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(), + legacy_request->app_info.ndp_app_info_len); + legacy_request->cipher_type = + (unsigned int)hidl_request.securityConfig.cipherType; + if (hidl_request.securityConfig.securityType == + NanDataPathSecurityType::PMK) { + legacy_request->key_info.key_type = + legacy_hal::NAN_SECURITY_KEY_INPUT_PMK; + legacy_request->key_info.body.pmk_info.pmk_len = + hidl_request.securityConfig.pmk.size(); + if (legacy_request->key_info.body.pmk_info.pmk_len != + NAN_PMK_INFO_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "invalid pmk_len"; + return false; + } + memcpy(legacy_request->key_info.body.pmk_info.pmk, + hidl_request.securityConfig.pmk.data(), + legacy_request->key_info.body.pmk_info.pmk_len); + } + if (hidl_request.securityConfig.securityType == + NanDataPathSecurityType::PASSPHRASE) { + legacy_request->key_info.key_type = + legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE; + legacy_request->key_info.body.passphrase_info.passphrase_len = + hidl_request.securityConfig.passphrase.size(); + if (legacy_request->key_info.body.passphrase_info.passphrase_len < + NAN_SECURITY_MIN_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "passphrase_len too small"; + return false; + } + if (legacy_request->key_info.body.passphrase_info.passphrase_len > + NAN_SECURITY_MAX_PASSPHRASE_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "passphrase_len too large"; + return false; + } + memcpy(legacy_request->key_info.body.passphrase_info.passphrase, + hidl_request.securityConfig.passphrase.data(), + legacy_request->key_info.body.passphrase_info.passphrase_len); + } + legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size(); + if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) { + LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: " + "service_name_len too large"; + return false; + } + memcpy(legacy_request->service_name, + hidl_request.serviceNameOutOfBand.data(), + legacy_request->service_name_len); + + return true; +} + +bool convertLegacyNanResponseHeaderToHidl( + const legacy_hal::NanResponseMsg& legacy_response, + WifiNanStatus* wifiNanStatus) { + if (!wifiNanStatus) { + LOG(ERROR) + << "convertLegacyNanResponseHeaderToHidl: wifiNanStatus is null"; + return false; + } + *wifiNanStatus = {}; + + convertToWifiNanStatus(legacy_response.status, legacy_response.nan_error, + sizeof(legacy_response.nan_error), wifiNanStatus); + return true; +} + +bool convertLegacyNanCapabilitiesResponseToHidl( + const legacy_hal::NanCapabilities& legacy_response, + NanCapabilities* hidl_response) { + if (!hidl_response) { + LOG(ERROR) << "convertLegacyNanCapabilitiesResponseToHidl: " + "hidl_response is null"; + return false; + } + *hidl_response = {}; + + hidl_response->maxConcurrentClusters = + legacy_response.max_concurrent_nan_clusters; + hidl_response->maxPublishes = legacy_response.max_publishes; + hidl_response->maxSubscribes = legacy_response.max_subscribes; + hidl_response->maxServiceNameLen = legacy_response.max_service_name_len; + hidl_response->maxMatchFilterLen = legacy_response.max_match_filter_len; + hidl_response->maxTotalMatchFilterLen = + legacy_response.max_total_match_filter_len; + hidl_response->maxServiceSpecificInfoLen = + legacy_response.max_service_specific_info_len; + hidl_response->maxExtendedServiceSpecificInfoLen = + legacy_response.max_sdea_service_specific_info_len; + hidl_response->maxNdiInterfaces = legacy_response.max_ndi_interfaces; + hidl_response->maxNdpSessions = legacy_response.max_ndp_sessions; + hidl_response->maxAppInfoLen = legacy_response.max_app_info_len; + hidl_response->maxQueuedTransmitFollowupMsgs = + legacy_response.max_queued_transmit_followup_msgs; + hidl_response->maxSubscribeInterfaceAddresses = + legacy_response.max_subscribe_address; + hidl_response->supportedCipherSuites = + legacy_response.cipher_suites_supported; + + return true; +} + +bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind, + NanMatchInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanMatchIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id; + hidl_ind->peerId = legacy_ind.requestor_instance_id; + hidl_ind->addr = hidl_array<uint8_t, 6>(legacy_ind.addr); + hidl_ind->serviceSpecificInfo = + std::vector<uint8_t>(legacy_ind.service_specific_info, + legacy_ind.service_specific_info + + legacy_ind.service_specific_info_len); + hidl_ind->extendedServiceSpecificInfo = + std::vector<uint8_t>(legacy_ind.sdea_service_specific_info, + legacy_ind.sdea_service_specific_info + + legacy_ind.sdea_service_specific_info_len); + hidl_ind->matchFilter = std::vector<uint8_t>( + legacy_ind.sdf_match_filter, + legacy_ind.sdf_match_filter + legacy_ind.sdf_match_filter_len); + hidl_ind->matchOccuredInBeaconFlag = legacy_ind.match_occured_flag == 1; + hidl_ind->outOfResourceFlag = legacy_ind.out_of_resource_flag == 1; + hidl_ind->rssiValue = legacy_ind.rssi_value; + hidl_ind->peerCipherType = (NanCipherSuiteType)legacy_ind.peer_cipher_type; + hidl_ind->peerRequiresSecurityEnabledInNdp = + legacy_ind.peer_sdea_params.security_cfg == + legacy_hal::NAN_DP_CONFIG_SECURITY; + hidl_ind->peerRequiresRanging = legacy_ind.peer_sdea_params.ranging_state == + legacy_hal::NAN_RANGING_ENABLE; + hidl_ind->rangingMeasurementInCm = + legacy_ind.range_info.range_measurement_mm / 10; + hidl_ind->rangingIndicationType = legacy_ind.range_info.ranging_event_type; + + return true; +} + +bool convertLegacyNanFollowupIndToHidl( + const legacy_hal::NanFollowupInd& legacy_ind, + NanFollowupReceivedInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanFollowupIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id; + hidl_ind->peerId = legacy_ind.requestor_instance_id; + hidl_ind->addr = hidl_array<uint8_t, 6>(legacy_ind.addr); + hidl_ind->receivedInFaw = legacy_ind.dw_or_faw == 1; + hidl_ind->serviceSpecificInfo = + std::vector<uint8_t>(legacy_ind.service_specific_info, + legacy_ind.service_specific_info + + legacy_ind.service_specific_info_len); + hidl_ind->extendedServiceSpecificInfo = + std::vector<uint8_t>(legacy_ind.sdea_service_specific_info, + legacy_ind.sdea_service_specific_info + + legacy_ind.sdea_service_specific_info_len); + + return true; +} + +bool convertLegacyNanDataPathRequestIndToHidl( + const legacy_hal::NanDataPathRequestInd& legacy_ind, + NanDataPathRequestInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) + << "convertLegacyNanDataPathRequestIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->discoverySessionId = legacy_ind.service_instance_id; + hidl_ind->peerDiscMacAddr = + hidl_array<uint8_t, 6>(legacy_ind.peer_disc_mac_addr); + hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id; + hidl_ind->securityRequired = + legacy_ind.ndp_cfg.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY; + hidl_ind->appInfo = + std::vector<uint8_t>(legacy_ind.app_info.ndp_app_info, + legacy_ind.app_info.ndp_app_info + + legacy_ind.app_info.ndp_app_info_len); + + return true; +} + +bool convertLegacyNdpChannelInfoToHidl( + const legacy_hal::NanChannelInfo& legacy_struct, + V1_2::NanDataPathChannelInfo* hidl_struct) { + if (!hidl_struct) { + LOG(ERROR) << "convertLegacyNdpChannelInfoToHidl: hidl_struct is null"; + return false; + } + *hidl_struct = {}; + + hidl_struct->channelFreq = legacy_struct.channel; + hidl_struct->channelBandwidth = convertLegacyWifiChannelWidthToHidl( + (legacy_hal::wifi_channel_width)legacy_struct.bandwidth); + hidl_struct->numSpatialStreams = legacy_struct.nss; + + return true; +} + +bool convertLegacyNanDataPathConfirmIndToHidl( + const legacy_hal::NanDataPathConfirmInd& legacy_ind, + V1_2::NanDataPathConfirmInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) + << "convertLegacyNanDataPathConfirmIndToHidl: hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->V1_0.ndpInstanceId = legacy_ind.ndp_instance_id; + hidl_ind->V1_0.dataPathSetupSuccess = + legacy_ind.rsp_code == legacy_hal::NAN_DP_REQUEST_ACCEPT; + hidl_ind->V1_0.peerNdiMacAddr = + hidl_array<uint8_t, 6>(legacy_ind.peer_ndi_mac_addr); + hidl_ind->V1_0.appInfo = + std::vector<uint8_t>(legacy_ind.app_info.ndp_app_info, + legacy_ind.app_info.ndp_app_info + + legacy_ind.app_info.ndp_app_info_len); + hidl_ind->V1_0.status.status = + convertLegacyNanStatusTypeToHidl(legacy_ind.reason_code); + hidl_ind->V1_0.status.description = ""; // TODO: b/34059183 + + std::vector<V1_2::NanDataPathChannelInfo> channelInfo; + for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) { + V1_2::NanDataPathChannelInfo hidl_struct; + if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i], + &hidl_struct)) { + return false; + } + channelInfo.push_back(hidl_struct); + } + hidl_ind->channelInfo = channelInfo; + + return true; +} + +bool convertLegacyNanDataPathScheduleUpdateIndToHidl( + const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind, + V1_2::NanDataPathScheduleUpdateInd* hidl_ind) { + if (!hidl_ind) { + LOG(ERROR) << "convertLegacyNanDataPathScheduleUpdateIndToHidl: " + "hidl_ind is null"; + return false; + } + *hidl_ind = {}; + + hidl_ind->peerDiscoveryAddress = + hidl_array<uint8_t, 6>(legacy_ind.peer_mac_addr); + std::vector<V1_2::NanDataPathChannelInfo> channelInfo; + for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) { + V1_2::NanDataPathChannelInfo hidl_struct; + if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i], + &hidl_struct)) { + return false; + } + channelInfo.push_back(hidl_struct); + } + hidl_ind->channelInfo = channelInfo; + std::vector<uint32_t> ndpInstanceIds; + for (unsigned int i = 0; i < legacy_ind.num_ndp_instances; ++i) { + ndpInstanceIds.push_back(legacy_ind.ndp_instance_id[i]); + } + hidl_ind->ndpInstanceIds = ndpInstanceIds; + + return true; +} + +legacy_hal::wifi_rtt_type convertHidlRttTypeToLegacy(RttType type) { + switch (type) { + case RttType::ONE_SIDED: + return legacy_hal::RTT_TYPE_1_SIDED; + case RttType::TWO_SIDED: + return legacy_hal::RTT_TYPE_2_SIDED; + }; + CHECK(false); +} + +RttType convertLegacyRttTypeToHidl(legacy_hal::wifi_rtt_type type) { + switch (type) { + case legacy_hal::RTT_TYPE_1_SIDED: + return RttType::ONE_SIDED; + case legacy_hal::RTT_TYPE_2_SIDED: + return RttType::TWO_SIDED; + }; + CHECK(false) << "Unknown legacy type: " << type; +} + +legacy_hal::rtt_peer_type convertHidlRttPeerTypeToLegacy(RttPeerType type) { + switch (type) { + case RttPeerType::AP: + return legacy_hal::RTT_PEER_AP; + case RttPeerType::STA: + return legacy_hal::RTT_PEER_STA; + case RttPeerType::P2P_GO: + return legacy_hal::RTT_PEER_P2P_GO; + case RttPeerType::P2P_CLIENT: + return legacy_hal::RTT_PEER_P2P_CLIENT; + case RttPeerType::NAN: + return legacy_hal::RTT_PEER_NAN; + }; + CHECK(false); +} + +legacy_hal::wifi_channel_width convertHidlWifiChannelWidthToLegacy( + WifiChannelWidthInMhz type) { + switch (type) { + case WifiChannelWidthInMhz::WIDTH_20: + return legacy_hal::WIFI_CHAN_WIDTH_20; + case WifiChannelWidthInMhz::WIDTH_40: + return legacy_hal::WIFI_CHAN_WIDTH_40; + case WifiChannelWidthInMhz::WIDTH_80: + return legacy_hal::WIFI_CHAN_WIDTH_80; + case WifiChannelWidthInMhz::WIDTH_160: + return legacy_hal::WIFI_CHAN_WIDTH_160; + case WifiChannelWidthInMhz::WIDTH_80P80: + return legacy_hal::WIFI_CHAN_WIDTH_80P80; + case WifiChannelWidthInMhz::WIDTH_5: + return legacy_hal::WIFI_CHAN_WIDTH_5; + case WifiChannelWidthInMhz::WIDTH_10: + return legacy_hal::WIFI_CHAN_WIDTH_10; + case WifiChannelWidthInMhz::WIDTH_INVALID: + return legacy_hal::WIFI_CHAN_WIDTH_INVALID; + }; + CHECK(false); +} + +WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl( + legacy_hal::wifi_channel_width type) { + switch (type) { + case legacy_hal::WIFI_CHAN_WIDTH_20: + return WifiChannelWidthInMhz::WIDTH_20; + case legacy_hal::WIFI_CHAN_WIDTH_40: + return WifiChannelWidthInMhz::WIDTH_40; + case legacy_hal::WIFI_CHAN_WIDTH_80: + return WifiChannelWidthInMhz::WIDTH_80; + case legacy_hal::WIFI_CHAN_WIDTH_160: + return WifiChannelWidthInMhz::WIDTH_160; + case legacy_hal::WIFI_CHAN_WIDTH_80P80: + return WifiChannelWidthInMhz::WIDTH_80P80; + case legacy_hal::WIFI_CHAN_WIDTH_5: + return WifiChannelWidthInMhz::WIDTH_5; + case legacy_hal::WIFI_CHAN_WIDTH_10: + return WifiChannelWidthInMhz::WIDTH_10; + case legacy_hal::WIFI_CHAN_WIDTH_INVALID: + return WifiChannelWidthInMhz::WIDTH_INVALID; + }; + CHECK(false) << "Unknown legacy type: " << type; +} + +legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(RttPreamble type) { + switch (type) { + case RttPreamble::LEGACY: + return legacy_hal::WIFI_RTT_PREAMBLE_LEGACY; + case RttPreamble::HT: + return legacy_hal::WIFI_RTT_PREAMBLE_HT; + case RttPreamble::VHT: + return legacy_hal::WIFI_RTT_PREAMBLE_VHT; + }; + CHECK(false); +} + +RttPreamble convertLegacyRttPreambleToHidl(legacy_hal::wifi_rtt_preamble type) { + switch (type) { + case legacy_hal::WIFI_RTT_PREAMBLE_LEGACY: + return RttPreamble::LEGACY; + case legacy_hal::WIFI_RTT_PREAMBLE_HT: + return RttPreamble::HT; + case legacy_hal::WIFI_RTT_PREAMBLE_VHT: + return RttPreamble::VHT; + }; + CHECK(false) << "Unknown legacy type: " << type; +} + +legacy_hal::wifi_rtt_bw convertHidlRttBwToLegacy(RttBw type) { + switch (type) { + case RttBw::BW_5MHZ: + return legacy_hal::WIFI_RTT_BW_5; + case RttBw::BW_10MHZ: + return legacy_hal::WIFI_RTT_BW_10; + case RttBw::BW_20MHZ: + return legacy_hal::WIFI_RTT_BW_20; + case RttBw::BW_40MHZ: + return legacy_hal::WIFI_RTT_BW_40; + case RttBw::BW_80MHZ: + return legacy_hal::WIFI_RTT_BW_80; + case RttBw::BW_160MHZ: + return legacy_hal::WIFI_RTT_BW_160; + }; + CHECK(false); +} + +RttBw convertLegacyRttBwToHidl(legacy_hal::wifi_rtt_bw type) { + switch (type) { + case legacy_hal::WIFI_RTT_BW_5: + return RttBw::BW_5MHZ; + case legacy_hal::WIFI_RTT_BW_10: + return RttBw::BW_10MHZ; + case legacy_hal::WIFI_RTT_BW_20: + return RttBw::BW_20MHZ; + case legacy_hal::WIFI_RTT_BW_40: + return RttBw::BW_40MHZ; + case legacy_hal::WIFI_RTT_BW_80: + return RttBw::BW_80MHZ; + case legacy_hal::WIFI_RTT_BW_160: + return RttBw::BW_160MHZ; + }; + CHECK(false) << "Unknown legacy type: " << type; +} + +legacy_hal::wifi_motion_pattern convertHidlRttMotionPatternToLegacy( + RttMotionPattern type) { + switch (type) { + case RttMotionPattern::NOT_EXPECTED: + return legacy_hal::WIFI_MOTION_NOT_EXPECTED; + case RttMotionPattern::EXPECTED: + return legacy_hal::WIFI_MOTION_EXPECTED; + case RttMotionPattern::UNKNOWN: + return legacy_hal::WIFI_MOTION_UNKNOWN; + }; + CHECK(false); +} + +WifiRatePreamble convertLegacyWifiRatePreambleToHidl(uint8_t preamble) { + switch (preamble) { + case 0: + return WifiRatePreamble::OFDM; + case 1: + return WifiRatePreamble::CCK; + case 2: + return WifiRatePreamble::HT; + case 3: + return WifiRatePreamble::VHT; + default: + return WifiRatePreamble::RESERVED; + }; + CHECK(false) << "Unknown legacy preamble: " << preamble; +} + +WifiRateNss convertLegacyWifiRateNssToHidl(uint8_t nss) { + switch (nss) { + case 0: + return WifiRateNss::NSS_1x1; + case 1: + return WifiRateNss::NSS_2x2; + case 2: + return WifiRateNss::NSS_3x3; + case 3: + return WifiRateNss::NSS_4x4; + }; + CHECK(false) << "Unknown legacy nss: " << nss; + return {}; +} + +RttStatus convertLegacyRttStatusToHidl(legacy_hal::wifi_rtt_status status) { + switch (status) { + case legacy_hal::RTT_STATUS_SUCCESS: + return RttStatus::SUCCESS; + case legacy_hal::RTT_STATUS_FAILURE: + return RttStatus::FAILURE; + case legacy_hal::RTT_STATUS_FAIL_NO_RSP: + return RttStatus::FAIL_NO_RSP; + case legacy_hal::RTT_STATUS_FAIL_REJECTED: + return RttStatus::FAIL_REJECTED; + case legacy_hal::RTT_STATUS_FAIL_NOT_SCHEDULED_YET: + return RttStatus::FAIL_NOT_SCHEDULED_YET; + case legacy_hal::RTT_STATUS_FAIL_TM_TIMEOUT: + return RttStatus::FAIL_TM_TIMEOUT; + case legacy_hal::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL: + return RttStatus::FAIL_AP_ON_DIFF_CHANNEL; + case legacy_hal::RTT_STATUS_FAIL_NO_CAPABILITY: + return RttStatus::FAIL_NO_CAPABILITY; + case legacy_hal::RTT_STATUS_ABORTED: + return RttStatus::ABORTED; + case legacy_hal::RTT_STATUS_FAIL_INVALID_TS: + return RttStatus::FAIL_INVALID_TS; + case legacy_hal::RTT_STATUS_FAIL_PROTOCOL: + return RttStatus::FAIL_PROTOCOL; + case legacy_hal::RTT_STATUS_FAIL_SCHEDULE: + return RttStatus::FAIL_SCHEDULE; + case legacy_hal::RTT_STATUS_FAIL_BUSY_TRY_LATER: + return RttStatus::FAIL_BUSY_TRY_LATER; + case legacy_hal::RTT_STATUS_INVALID_REQ: + return RttStatus::INVALID_REQ; + case legacy_hal::RTT_STATUS_NO_WIFI: + return RttStatus::NO_WIFI; + case legacy_hal::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE: + return RttStatus::FAIL_FTM_PARAM_OVERRIDE; + case legacy_hal::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE: + return RttStatus::FAILURE; // TODO: add HIDL enumeration + case legacy_hal::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED: + return RttStatus::FAILURE; // TODO: add HIDL enumeration + }; + CHECK(false) << "Unknown legacy status: " << status; +} + +bool convertHidlWifiChannelInfoToLegacy( + const WifiChannelInfo& hidl_info, + legacy_hal::wifi_channel_info* legacy_info) { + if (!legacy_info) { + return false; + } + *legacy_info = {}; + legacy_info->width = convertHidlWifiChannelWidthToLegacy(hidl_info.width); + legacy_info->center_freq = hidl_info.centerFreq; + legacy_info->center_freq0 = hidl_info.centerFreq0; + legacy_info->center_freq1 = hidl_info.centerFreq1; + return true; +} + +bool convertLegacyWifiChannelInfoToHidl( + const legacy_hal::wifi_channel_info& legacy_info, + WifiChannelInfo* hidl_info) { + if (!hidl_info) { + return false; + } + *hidl_info = {}; + hidl_info->width = convertLegacyWifiChannelWidthToHidl(legacy_info.width); + hidl_info->centerFreq = legacy_info.center_freq; + hidl_info->centerFreq0 = legacy_info.center_freq0; + hidl_info->centerFreq1 = legacy_info.center_freq1; + return true; +} + +bool convertHidlRttConfigToLegacy(const RttConfig& hidl_config, + legacy_hal::wifi_rtt_config* legacy_config) { + if (!legacy_config) { + return false; + } + *legacy_config = {}; + CHECK(hidl_config.addr.size() == sizeof(legacy_config->addr)); + memcpy(legacy_config->addr, hidl_config.addr.data(), + hidl_config.addr.size()); + legacy_config->type = convertHidlRttTypeToLegacy(hidl_config.type); + legacy_config->peer = convertHidlRttPeerTypeToLegacy(hidl_config.peer); + if (!convertHidlWifiChannelInfoToLegacy(hidl_config.channel, + &legacy_config->channel)) { + return false; + } + legacy_config->burst_period = hidl_config.burstPeriod; + legacy_config->num_burst = hidl_config.numBurst; + legacy_config->num_frames_per_burst = hidl_config.numFramesPerBurst; + legacy_config->num_retries_per_rtt_frame = + hidl_config.numRetriesPerRttFrame; + legacy_config->num_retries_per_ftmr = hidl_config.numRetriesPerFtmr; + legacy_config->LCI_request = hidl_config.mustRequestLci; + legacy_config->LCR_request = hidl_config.mustRequestLcr; + legacy_config->burst_duration = hidl_config.burstDuration; + legacy_config->preamble = + convertHidlRttPreambleToLegacy(hidl_config.preamble); + legacy_config->bw = convertHidlRttBwToLegacy(hidl_config.bw); + return true; +} + +bool convertHidlVectorOfRttConfigToLegacy( + const std::vector<RttConfig>& hidl_configs, + std::vector<legacy_hal::wifi_rtt_config>* legacy_configs) { + if (!legacy_configs) { + return false; + } + *legacy_configs = {}; + for (const auto& hidl_config : hidl_configs) { + legacy_hal::wifi_rtt_config legacy_config; + if (!convertHidlRttConfigToLegacy(hidl_config, &legacy_config)) { + return false; + } + legacy_configs->push_back(legacy_config); + } + return true; +} + +bool convertHidlRttLciInformationToLegacy( + const RttLciInformation& hidl_info, + legacy_hal::wifi_lci_information* legacy_info) { + if (!legacy_info) { + return false; + } + *legacy_info = {}; + legacy_info->latitude = hidl_info.latitude; + legacy_info->longitude = hidl_info.longitude; + legacy_info->altitude = hidl_info.altitude; + legacy_info->latitude_unc = hidl_info.latitudeUnc; + legacy_info->longitude_unc = hidl_info.longitudeUnc; + legacy_info->altitude_unc = hidl_info.altitudeUnc; + legacy_info->motion_pattern = + convertHidlRttMotionPatternToLegacy(hidl_info.motionPattern); + legacy_info->floor = hidl_info.floor; + legacy_info->height_above_floor = hidl_info.heightAboveFloor; + legacy_info->height_unc = hidl_info.heightUnc; + return true; +} + +bool convertHidlRttLcrInformationToLegacy( + const RttLcrInformation& hidl_info, + legacy_hal::wifi_lcr_information* legacy_info) { + if (!legacy_info) { + return false; + } + *legacy_info = {}; + CHECK(hidl_info.countryCode.size() == sizeof(legacy_info->country_code)); + memcpy(legacy_info->country_code, hidl_info.countryCode.data(), + hidl_info.countryCode.size()); + if (hidl_info.civicInfo.size() > sizeof(legacy_info->civic_info)) { + return false; + } + legacy_info->length = hidl_info.civicInfo.size(); + memcpy(legacy_info->civic_info, hidl_info.civicInfo.c_str(), + hidl_info.civicInfo.size()); + return true; +} + +bool convertHidlRttResponderToLegacy( + const RttResponder& hidl_responder, + legacy_hal::wifi_rtt_responder* legacy_responder) { + if (!legacy_responder) { + return false; + } + *legacy_responder = {}; + if (!convertHidlWifiChannelInfoToLegacy(hidl_responder.channel, + &legacy_responder->channel)) { + return false; + } + legacy_responder->preamble = + convertHidlRttPreambleToLegacy(hidl_responder.preamble); + return true; +} + +bool convertLegacyRttResponderToHidl( + const legacy_hal::wifi_rtt_responder& legacy_responder, + RttResponder* hidl_responder) { + if (!hidl_responder) { + return false; + } + *hidl_responder = {}; + if (!convertLegacyWifiChannelInfoToHidl(legacy_responder.channel, + &hidl_responder->channel)) { + return false; + } + hidl_responder->preamble = + convertLegacyRttPreambleToHidl(legacy_responder.preamble); + return true; +} + +bool convertLegacyRttCapabilitiesToHidl( + const legacy_hal::wifi_rtt_capabilities& legacy_capabilities, + RttCapabilities* hidl_capabilities) { + if (!hidl_capabilities) { + return false; + } + *hidl_capabilities = {}; + hidl_capabilities->rttOneSidedSupported = + legacy_capabilities.rtt_one_sided_supported; + hidl_capabilities->rttFtmSupported = legacy_capabilities.rtt_ftm_supported; + hidl_capabilities->lciSupported = legacy_capabilities.lci_support; + hidl_capabilities->lcrSupported = legacy_capabilities.lcr_support; + hidl_capabilities->responderSupported = + legacy_capabilities.responder_supported; + hidl_capabilities->preambleSupport = 0; + for (const auto flag : {legacy_hal::WIFI_RTT_PREAMBLE_LEGACY, + legacy_hal::WIFI_RTT_PREAMBLE_HT, + legacy_hal::WIFI_RTT_PREAMBLE_VHT}) { + if (legacy_capabilities.preamble_support & flag) { + hidl_capabilities->preambleSupport |= + static_cast<std::underlying_type<RttPreamble>::type>( + convertLegacyRttPreambleToHidl(flag)); + } + } + hidl_capabilities->bwSupport = 0; + for (const auto flag : + {legacy_hal::WIFI_RTT_BW_5, legacy_hal::WIFI_RTT_BW_10, + legacy_hal::WIFI_RTT_BW_20, legacy_hal::WIFI_RTT_BW_40, + legacy_hal::WIFI_RTT_BW_80, legacy_hal::WIFI_RTT_BW_160}) { + if (legacy_capabilities.bw_support & flag) { + hidl_capabilities->bwSupport |= + static_cast<std::underlying_type<RttBw>::type>( + convertLegacyRttBwToHidl(flag)); + } + } + hidl_capabilities->mcVersion = legacy_capabilities.mc_version; + return true; +} + +bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate, + WifiRateInfo* hidl_rate) { + if (!hidl_rate) { + return false; + } + *hidl_rate = {}; + hidl_rate->preamble = + convertLegacyWifiRatePreambleToHidl(legacy_rate.preamble); + hidl_rate->nss = convertLegacyWifiRateNssToHidl(legacy_rate.nss); + hidl_rate->bw = convertLegacyWifiChannelWidthToHidl( + static_cast<legacy_hal::wifi_channel_width>(legacy_rate.bw)); + hidl_rate->rateMcsIdx = legacy_rate.rateMcsIdx; + hidl_rate->bitRateInKbps = legacy_rate.bitrate; + return true; +} + +bool convertLegacyRttResultToHidl( + const legacy_hal::wifi_rtt_result& legacy_result, RttResult* hidl_result) { + if (!hidl_result) { + return false; + } + *hidl_result = {}; + CHECK(sizeof(legacy_result.addr) == hidl_result->addr.size()); + memcpy(hidl_result->addr.data(), legacy_result.addr, + sizeof(legacy_result.addr)); + hidl_result->burstNum = legacy_result.burst_num; + hidl_result->measurementNumber = legacy_result.measurement_number; + hidl_result->successNumber = legacy_result.success_number; + hidl_result->numberPerBurstPeer = legacy_result.number_per_burst_peer; + hidl_result->status = convertLegacyRttStatusToHidl(legacy_result.status); + hidl_result->retryAfterDuration = legacy_result.retry_after_duration; + hidl_result->type = convertLegacyRttTypeToHidl(legacy_result.type); + hidl_result->rssi = legacy_result.rssi; + hidl_result->rssiSpread = legacy_result.rssi_spread; + if (!convertLegacyWifiRateInfoToHidl(legacy_result.tx_rate, + &hidl_result->txRate)) { + return false; + } + if (!convertLegacyWifiRateInfoToHidl(legacy_result.rx_rate, + &hidl_result->rxRate)) { + return false; + } + hidl_result->rtt = legacy_result.rtt; + hidl_result->rttSd = legacy_result.rtt_sd; + hidl_result->rttSpread = legacy_result.rtt_spread; + hidl_result->distanceInMm = legacy_result.distance_mm; + hidl_result->distanceSdInMm = legacy_result.distance_sd_mm; + hidl_result->distanceSpreadInMm = legacy_result.distance_spread_mm; + hidl_result->timeStampInUs = legacy_result.ts; + hidl_result->burstDurationInMs = legacy_result.burst_duration; + hidl_result->negotiatedBurstNum = legacy_result.negotiated_burst_num; + if (legacy_result.LCI && + !convertLegacyIeToHidl(*legacy_result.LCI, &hidl_result->lci)) { + return false; + } + if (legacy_result.LCR && + !convertLegacyIeToHidl(*legacy_result.LCR, &hidl_result->lcr)) { + return false; + } + return true; +} + +bool convertLegacyVectorOfRttResultToHidl( + const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results, + std::vector<RttResult>* hidl_results) { + if (!hidl_results) { + return false; + } + *hidl_results = {}; + for (const auto legacy_result : legacy_results) { + RttResult hidl_result; + if (!convertLegacyRttResultToHidl(*legacy_result, &hidl_result)) { + return false; + } + hidl_results->push_back(hidl_result); + } + return true; +} +} // namespace hidl_struct_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/hidl_struct_util.h b/wifi/1.0/hidl_struct_util.h new file mode 100644 index 0000000..3eefd95 --- /dev/null +++ b/wifi/1.0/hidl_struct_util.h @@ -0,0 +1,196 @@ +/* + * 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 HIDL_STRUCT_UTIL_H_ +#define HIDL_STRUCT_UTIL_H_ + +#include <vector> + +#include <android/hardware/wifi/1.0/IWifiChip.h> +#include <android/hardware/wifi/1.0/types.h> +#include <android/hardware/wifi/1.2/IWifiChipEventCallback.h> +#include <android/hardware/wifi/1.2/types.h> +#include <android/hardware/wifi/1.3/IWifiChip.h> +#include <android/hardware/wifi/1.3/types.h> + +#include "wifi_legacy_hal.h" + +/** + * This file contains a bunch of functions to convert structs from the legacy + * HAL to HIDL and vice versa. + * TODO(b/32093047): Add unit tests for these conversion methods in the VTS test + * suite. + */ +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace hidl_struct_util { +using namespace android::hardware::wifi::V1_0; + +// Chip conversion methods. +bool convertLegacyFeaturesToHidlChipCapabilities( + uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set, + uint32_t* hidl_caps); +bool convertLegacyDebugRingBufferStatusToHidl( + const legacy_hal::wifi_ring_buffer_status& legacy_status, + WifiDebugRingBufferStatus* hidl_status); +bool convertLegacyVectorOfDebugRingBufferStatusToHidl( + const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec, + std::vector<WifiDebugRingBufferStatus>* hidl_status_vec); +bool convertLegacyWakeReasonStatsToHidl( + const legacy_hal::WakeReasonStats& legacy_stats, + WifiDebugHostWakeReasonStats* hidl_stats); +legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy( + V1_1::IWifiChip::TxPowerScenario hidl_scenario); +legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy( + V1_3::IWifiChip::LatencyMode hidl_latency_mode); +legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2( + V1_2::IWifiChip::TxPowerScenario hidl_scenario); +bool convertLegacyWifiMacInfosToHidl( + const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos, + std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo>* + hidl_radio_mode_infos); + +// STA iface conversion methods. +bool convertLegacyFeaturesToHidlStaCapabilities( + uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set, + uint32_t* hidl_caps); +bool convertLegacyApfCapabilitiesToHidl( + const legacy_hal::PacketFilterCapabilities& legacy_caps, + StaApfPacketFilterCapabilities* hidl_caps); +bool convertLegacyGscanCapabilitiesToHidl( + const legacy_hal::wifi_gscan_capabilities& legacy_caps, + StaBackgroundScanCapabilities* hidl_caps); +legacy_hal::wifi_band convertHidlWifiBandToLegacy(WifiBand band); +bool convertHidlGscanParamsToLegacy( + const StaBackgroundScanParameters& hidl_scan_params, + legacy_hal::wifi_scan_cmd_params* legacy_scan_params); +// |has_ie_data| indicates whether or not the wifi_scan_result includes 802.11 +// Information Elements (IEs) +bool convertLegacyGscanResultToHidl( + const legacy_hal::wifi_scan_result& legacy_scan_result, bool has_ie_data, + StaScanResult* hidl_scan_result); +// |cached_results| is assumed to not include IEs. +bool convertLegacyVectorOfCachedGscanResultsToHidl( + const std::vector<legacy_hal::wifi_cached_scan_results>& + legacy_cached_scan_results, + std::vector<StaScanData>* hidl_scan_datas); +bool convertLegacyLinkLayerStatsToHidl( + const legacy_hal::LinkLayerStats& legacy_stats, + V1_3::StaLinkLayerStats* hidl_stats); +bool convertLegacyRoamingCapabilitiesToHidl( + const legacy_hal::wifi_roaming_capabilities& legacy_caps, + StaRoamingCapabilities* hidl_caps); +bool convertHidlRoamingConfigToLegacy( + const StaRoamingConfig& hidl_config, + legacy_hal::wifi_roaming_config* legacy_config); +legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy( + StaRoamingState state); +bool convertLegacyVectorOfDebugTxPacketFateToHidl( + const std::vector<legacy_hal::wifi_tx_report>& legacy_fates, + std::vector<WifiDebugTxPacketFateReport>* hidl_fates); +bool convertLegacyVectorOfDebugRxPacketFateToHidl( + const std::vector<legacy_hal::wifi_rx_report>& legacy_fates, + std::vector<WifiDebugRxPacketFateReport>* hidl_fates); + +// NAN iface conversion methods. +void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, + size_t max_len, WifiNanStatus* wifiNanStatus); +bool convertHidlNanEnableRequestToLegacy( + const NanEnableRequest& hidl_request, + legacy_hal::NanEnableRequest* legacy_request); +bool convertHidlNanConfigRequestToLegacy( + const NanConfigRequest& hidl_request, + legacy_hal::NanConfigRequest* legacy_request); +bool convertHidlNanEnableRequest_1_2ToLegacy( + const NanEnableRequest& hidl_request1, + const V1_2::NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanEnableRequest* legacy_request); +bool convertHidlNanConfigRequest_1_2ToLegacy( + const NanConfigRequest& hidl_request1, + const V1_2::NanConfigRequestSupplemental& hidl_request2, + legacy_hal::NanConfigRequest* legacy_request); +bool convertHidlNanPublishRequestToLegacy( + const NanPublishRequest& hidl_request, + legacy_hal::NanPublishRequest* legacy_request); +bool convertHidlNanSubscribeRequestToLegacy( + const NanSubscribeRequest& hidl_request, + legacy_hal::NanSubscribeRequest* legacy_request); +bool convertHidlNanTransmitFollowupRequestToLegacy( + const NanTransmitFollowupRequest& hidl_request, + legacy_hal::NanTransmitFollowupRequest* legacy_request); +bool convertHidlNanDataPathInitiatorRequestToLegacy( + const NanInitiateDataPathRequest& hidl_request, + legacy_hal::NanDataPathInitiatorRequest* legacy_request); +bool convertHidlNanDataPathIndicationResponseToLegacy( + const NanRespondToDataPathIndicationRequest& hidl_response, + legacy_hal::NanDataPathIndicationResponse* legacy_response); +bool convertLegacyNanResponseHeaderToHidl( + const legacy_hal::NanResponseMsg& legacy_response, + WifiNanStatus* wifiNanStatus); +bool convertLegacyNanCapabilitiesResponseToHidl( + const legacy_hal::NanCapabilities& legacy_response, + NanCapabilities* hidl_response); +bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind, + NanMatchInd* hidl_ind); +bool convertLegacyNanFollowupIndToHidl( + const legacy_hal::NanFollowupInd& legacy_ind, + NanFollowupReceivedInd* hidl_ind); +bool convertLegacyNanDataPathRequestIndToHidl( + const legacy_hal::NanDataPathRequestInd& legacy_ind, + NanDataPathRequestInd* hidl_ind); +bool convertLegacyNanDataPathConfirmIndToHidl( + const legacy_hal::NanDataPathConfirmInd& legacy_ind, + V1_2::NanDataPathConfirmInd* hidl_ind); +bool convertLegacyNanDataPathScheduleUpdateIndToHidl( + const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind, + V1_2::NanDataPathScheduleUpdateInd* hidl_ind); + +// RTT controller conversion methods. +bool convertHidlVectorOfRttConfigToLegacy( + const std::vector<RttConfig>& hidl_configs, + std::vector<legacy_hal::wifi_rtt_config>* legacy_configs); +bool convertHidlRttLciInformationToLegacy( + const RttLciInformation& hidl_info, + legacy_hal::wifi_lci_information* legacy_info); +bool convertHidlRttLcrInformationToLegacy( + const RttLcrInformation& hidl_info, + legacy_hal::wifi_lcr_information* legacy_info); +bool convertHidlRttResponderToLegacy( + const RttResponder& hidl_responder, + legacy_hal::wifi_rtt_responder* legacy_responder); +bool convertHidlWifiChannelInfoToLegacy( + const WifiChannelInfo& hidl_info, + legacy_hal::wifi_channel_info* legacy_info); +bool convertLegacyRttResponderToHidl( + const legacy_hal::wifi_rtt_responder& legacy_responder, + RttResponder* hidl_responder); +bool convertLegacyRttCapabilitiesToHidl( + const legacy_hal::wifi_rtt_capabilities& legacy_capabilities, + RttCapabilities* hidl_capabilities); +bool convertLegacyVectorOfRttResultToHidl( + const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results, + std::vector<RttResult>* hidl_results); +} // namespace hidl_struct_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // HIDL_STRUCT_UTIL_H_ diff --git a/wifi/1.0/hidl_sync_util.cpp b/wifi/1.0/hidl_sync_util.cpp new file mode 100644 index 0000000..160727f --- /dev/null +++ b/wifi/1.0/hidl_sync_util.cpp @@ -0,0 +1,39 @@ +/* + * 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 "hidl_sync_util.h" + +namespace { +std::recursive_mutex g_mutex; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace hidl_sync_util { + +std::unique_lock<std::recursive_mutex> acquireGlobalLock() { + return std::unique_lock<std::recursive_mutex>{g_mutex}; +} + +} // namespace hidl_sync_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/hidl_sync_util.h b/wifi/1.0/hidl_sync_util.h new file mode 100644 index 0000000..ebfb051 --- /dev/null +++ b/wifi/1.0/hidl_sync_util.h @@ -0,0 +1,37 @@ +/* + * 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 HIDL_SYNC_UTIL_H_ +#define HIDL_SYNC_UTIL_H_ + +#include <mutex> + +// Utility that provides a global lock to synchronize access between +// the HIDL thread and the legacy HAL's event loop. +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace hidl_sync_util { +std::unique_lock<std::recursive_mutex> acquireGlobalLock(); +} // namespace hidl_sync_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // HIDL_SYNC_UTIL_H_ diff --git a/wifi/1.0/ringbuffer.cpp b/wifi/1.0/ringbuffer.cpp new file mode 100644 index 0000000..1294c52 --- /dev/null +++ b/wifi/1.0/ringbuffer.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/logging.h> + +#include "ringbuffer.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { + +Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {} + +void Ringbuffer::append(const std::vector<uint8_t>& input) { + if (input.size() == 0) { + return; + } + if (input.size() > maxSize_) { + LOG(INFO) << "Oversized message of " << input.size() + << " bytes is dropped"; + return; + } + data_.push_back(input); + size_ += input.size() * sizeof(input[0]); + while (size_ > maxSize_) { + size_ -= data_.front().size() * sizeof(data_.front()[0]); + data_.pop_front(); + } +} + +const std::list<std::vector<uint8_t>>& Ringbuffer::getData() const { + return data_; +} + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/ringbuffer.h b/wifi/1.0/ringbuffer.h new file mode 100644 index 0000000..d9f8df6 --- /dev/null +++ b/wifi/1.0/ringbuffer.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2018 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 RINGBUFFER_H_ +#define RINGBUFFER_H_ + +#include <list> +#include <vector> + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { + +/** + * Ringbuffer object used to store debug data. + */ +class Ringbuffer { + public: + explicit Ringbuffer(size_t maxSize); + + // Appends the data buffer and deletes from the front until buffer is + // within |maxSize_|. + void append(const std::vector<uint8_t>& input); + const std::list<std::vector<uint8_t>>& getData() const; + + private: + std::list<std::vector<uint8_t>> data_; + size_t size_; + size_t maxSize_; +}; + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // RINGBUFFER_H_ diff --git a/wifi/1.0/service.cpp b/wifi/1.0/service.cpp new file mode 100644 index 0000000..fcbc37c --- /dev/null +++ b/wifi/1.0/service.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/logging.h> +#include <hidl/HidlLazyUtils.h> +#include <hidl/HidlTransportSupport.h> +#include <utils/Looper.h> +#include <utils/StrongPointer.h> + +#include "wifi.h" +#include "wifi_feature_flags.h" +#include "wifi_legacy_hal.h" +#include "wifi_mode_controller.h" + +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::hardware::LazyServiceRegistrar; +using android::hardware::wifi::V1_3::implementation::feature_flags:: + WifiFeatureFlags; +using android::hardware::wifi::V1_3::implementation::iface_util::WifiIfaceUtil; +using android::hardware::wifi::V1_3::implementation::legacy_hal::WifiLegacyHal; +using android::hardware::wifi::V1_3::implementation::mode_controller:: + WifiModeController; + +#ifdef LAZY_SERVICE +const bool kLazyService = true; +#else +const bool kLazyService = false; +#endif + +int main(int /*argc*/, char** argv) { + android::base::InitLogging( + argv, android::base::LogdLogger(android::base::SYSTEM)); + LOG(INFO) << "Wifi Hal is booting up..."; + + configureRpcThreadpool(1, true /* callerWillJoin */); + + const auto iface_tool = + std::make_shared<android::wifi_system::InterfaceTool>(); + // Setup hwbinder service + android::sp<android::hardware::wifi::V1_3::IWifi> service = + new android::hardware::wifi::V1_3::implementation::Wifi( + iface_tool, std::make_shared<WifiLegacyHal>(iface_tool), + std::make_shared<WifiModeController>(), + std::make_shared<WifiIfaceUtil>(iface_tool), + std::make_shared<WifiFeatureFlags>()); + if (kLazyService) { + LazyServiceRegistrar registrar; + CHECK_EQ(registrar.registerService(service), android::NO_ERROR) + << "Failed to register wifi HAL"; + } else { + CHECK_EQ(service->registerAsService(), android::NO_ERROR) + << "Failed to register wifi HAL"; + } + + joinRpcThreadpool(); + + LOG(INFO) << "Wifi Hal is terminating..."; + return 0; +} diff --git a/wifi/1.0/wifi.cpp b/wifi/1.0/wifi.cpp new file mode 100644 index 0000000..2f21819 --- /dev/null +++ b/wifi/1.0/wifi.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/logging.h> + +#include "hidl_return_util.h" +#include "wifi.h" +#include "wifi_status_util.h" + +namespace { +// Chip ID to use for the only supported chip. +static constexpr android::hardware::wifi::V1_0::ChipId kChipId = 0; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using hidl_return_util::validateAndCall; +using hidl_return_util::validateAndCallWithLock; + +Wifi::Wifi( + const std::shared_ptr<wifi_system::InterfaceTool> iface_tool, + const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::shared_ptr<mode_controller::WifiModeController> mode_controller, + const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util, + const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags) + : iface_tool_(iface_tool), + legacy_hal_(legacy_hal), + mode_controller_(mode_controller), + iface_util_(iface_util), + feature_flags_(feature_flags), + run_state_(RunState::STOPPED) {} + +bool Wifi::isValid() { + // This object is always valid. + return true; +} + +Return<void> Wifi::registerEventCallback( + const sp<IWifiEventCallback>& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, + &Wifi::registerEventCallbackInternal, hidl_status_cb, + event_callback); +} + +Return<bool> Wifi::isStarted() { return run_state_ != RunState::STOPPED; } + +Return<void> Wifi::start(start_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, + &Wifi::startInternal, hidl_status_cb); +} + +Return<void> Wifi::stop(stop_cb hidl_status_cb) { + return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN, + &Wifi::stopInternal, hidl_status_cb); +} + +Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, + &Wifi::getChipIdsInternal, hidl_status_cb); +} + +Return<void> Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, + &Wifi::getChipInternal, hidl_status_cb, chip_id); +} + +Return<void> Wifi::debug(const hidl_handle& handle, + const hidl_vec<hidl_string>&) { + LOG(INFO) << "-----------Debug is called----------------"; + if (!chip_.get()) { + return Void(); + } + return chip_->debug(handle, {}); +} + +WifiStatus Wifi::registerEventCallbackInternal( + const sp<IWifiEventCallback>& event_callback) { + if (!event_cb_handler_.addCallback(event_callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus Wifi::startInternal() { + if (run_state_ == RunState::STARTED) { + return createWifiStatus(WifiStatusCode::SUCCESS); + } else if (run_state_ == RunState::STOPPING) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, + "HAL is stopping"); + } + WifiStatus wifi_status = initializeModeControllerAndLegacyHal(); + if (wifi_status.code == WifiStatusCode::SUCCESS) { + // Create the chip instance once the HAL is started. + chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_, + iface_util_, feature_flags_); + run_state_ = RunState::STARTED; + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onStart().isOk()) { + LOG(ERROR) << "Failed to invoke onStart callback"; + }; + } + LOG(INFO) << "Wifi HAL started"; + } else { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onFailure(wifi_status).isOk()) { + LOG(ERROR) << "Failed to invoke onFailure callback"; + } + } + LOG(ERROR) << "Wifi HAL start failed"; + } + return wifi_status; +} + +WifiStatus Wifi::stopInternal( + /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) { + if (run_state_ == RunState::STOPPED) { + return createWifiStatus(WifiStatusCode::SUCCESS); + } else if (run_state_ == RunState::STOPPING) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, + "HAL is stopping"); + } + // Clear the chip object and its child objects since the HAL is now + // stopped. + if (chip_.get()) { + chip_->invalidate(); + chip_.clear(); + } + WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock); + if (wifi_status.code == WifiStatusCode::SUCCESS) { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onStop().isOk()) { + LOG(ERROR) << "Failed to invoke onStop callback"; + }; + } + LOG(INFO) << "Wifi HAL stopped"; + } else { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onFailure(wifi_status).isOk()) { + LOG(ERROR) << "Failed to invoke onFailure callback"; + } + } + LOG(ERROR) << "Wifi HAL stop failed"; + } + return wifi_status; +} + +std::pair<WifiStatus, std::vector<ChipId>> Wifi::getChipIdsInternal() { + std::vector<ChipId> chip_ids; + if (chip_.get()) { + chip_ids.emplace_back(kChipId); + } + return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)}; +} + +std::pair<WifiStatus, sp<IWifiChip>> Wifi::getChipInternal(ChipId chip_id) { + if (!chip_.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_STARTED), nullptr}; + } + if (chip_id != kChipId) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), chip_}; +} + +WifiStatus Wifi::initializeModeControllerAndLegacyHal() { + if (!mode_controller_->initialize()) { + LOG(ERROR) << "Failed to initialize firmware mode controller"; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + legacy_hal::wifi_error legacy_status = legacy_hal_->initialize(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to initialize legacy HAL: " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController( + /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) { + run_state_ = RunState::STOPPING; + legacy_hal::wifi_error legacy_status = + legacy_hal_->stop(lock, [&]() { run_state_ = RunState::STOPPED; }); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to stop legacy HAL: " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + if (!mode_controller_->deinitialize()) { + LOG(ERROR) << "Failed to deinitialize firmware mode controller"; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi.h b/wifi/1.0/wifi.h new file mode 100644 index 0000000..1c2a154 --- /dev/null +++ b/wifi/1.0/wifi.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WIFI_H_ +#define WIFI_H_ + +#include <functional> + +#include <android-base/macros.h> +#include <android/hardware/wifi/1.3/IWifi.h> +#include <utils/Looper.h> + +#include "hidl_callback_util.h" +#include "wifi_chip.h" +#include "wifi_feature_flags.h" +#include "wifi_legacy_hal.h" +#include "wifi_mode_controller.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { + +/** + * Root HIDL interface object used to control the Wifi HAL. + */ +class Wifi : public V1_3::IWifi { + public: + Wifi(const std::shared_ptr<wifi_system::InterfaceTool> iface_tool, + const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::shared_ptr<mode_controller::WifiModeController> + mode_controller, + const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util, + const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags); + + bool isValid(); + + // HIDL methods exposed. + Return<void> registerEventCallback( + const sp<IWifiEventCallback>& event_callback, + registerEventCallback_cb hidl_status_cb) override; + Return<bool> isStarted() override; + Return<void> start(start_cb hidl_status_cb) override; + Return<void> stop(stop_cb hidl_status_cb) override; + Return<void> getChipIds(getChipIds_cb hidl_status_cb) override; + Return<void> getChip(ChipId chip_id, getChip_cb hidl_status_cb) override; + Return<void> debug(const hidl_handle& handle, + const hidl_vec<hidl_string>& options) override; + + private: + enum class RunState { STOPPED, STARTED, STOPPING }; + + // Corresponding worker functions for the HIDL methods. + WifiStatus registerEventCallbackInternal( + const sp<IWifiEventCallback>& event_callback); + WifiStatus startInternal(); + WifiStatus stopInternal(std::unique_lock<std::recursive_mutex>* lock); + std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal(); + std::pair<WifiStatus, sp<IWifiChip>> getChipInternal(ChipId chip_id); + + WifiStatus initializeModeControllerAndLegacyHal(); + WifiStatus stopLegacyHalAndDeinitializeModeController( + std::unique_lock<std::recursive_mutex>* lock); + + // Instance is created in this root level |IWifi| HIDL interface object + // and shared with all the child HIDL interface objects. + std::shared_ptr<wifi_system::InterfaceTool> iface_tool_; + std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + std::shared_ptr<mode_controller::WifiModeController> mode_controller_; + std::shared_ptr<iface_util::WifiIfaceUtil> iface_util_; + std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags_; + RunState run_state_; + sp<WifiChip> chip_; + hidl_callback_util::HidlCallbackHandler<IWifiEventCallback> + event_cb_handler_; + + DISALLOW_COPY_AND_ASSIGN(Wifi); +}; + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_H_ diff --git a/wifi/1.0/wifi_ap_iface.cpp b/wifi/1.0/wifi_ap_iface.cpp new file mode 100644 index 0000000..9a8681a --- /dev/null +++ b/wifi/1.0/wifi_ap_iface.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/logging.h> + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_ap_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiApIface::WifiApIface( + const std::string& ifname, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util, + const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags) + : ifname_(ifname), + legacy_hal_(legacy_hal), + iface_util_(iface_util), + feature_flags_(feature_flags), + is_valid_(true) { + if (feature_flags_.lock()->isApMacRandomizationDisabled()) { + LOG(INFO) << "AP MAC randomization disabled"; + return; + } + LOG(INFO) << "AP MAC randomization enabled"; + // Set random MAC address + std::array<uint8_t, 6> randomized_mac = + iface_util_.lock()->getOrCreateRandomMacAddress(); + bool status = iface_util_.lock()->setMacAddress(ifname_, randomized_mac); + if (!status) { + LOG(ERROR) << "Failed to set random mac address"; + } +} + +void WifiApIface::invalidate() { + legacy_hal_.reset(); + is_valid_ = false; +} + +bool WifiApIface::isValid() { return is_valid_; } + +std::string WifiApIface::getName() { return ifname_; } + +Return<void> WifiApIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getNameInternal, hidl_status_cb); +} + +Return<void> WifiApIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getTypeInternal, hidl_status_cb); +} + +Return<void> WifiApIface::setCountryCode(const hidl_array<int8_t, 2>& code, + setCountryCode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::setCountryCodeInternal, hidl_status_cb, + code); +} + +Return<void> WifiApIface::getValidFrequenciesForBand( + WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiApIface::getValidFrequenciesForBandInternal, + hidl_status_cb, band); +} + +std::pair<WifiStatus, std::string> WifiApIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair<WifiStatus, IfaceType> WifiApIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::AP}; +} + +WifiStatus WifiApIface::setCountryCodeInternal( + const std::array<int8_t, 2>& code) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setCountryCode(ifname_, code); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, std::vector<WifiChannelInMhz>> +WifiApIface::getValidFrequenciesForBandInternal(WifiBand band) { + static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), + "Size mismatch"); + legacy_hal::wifi_error legacy_status; + std::vector<uint32_t> valid_frequencies; + std::tie(legacy_status, valid_frequencies) = + legacy_hal_.lock()->getValidFrequenciesForBand( + ifname_, hidl_struct_util::convertHidlWifiBandToLegacy(band)); + return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies}; +} +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi_ap_iface.h b/wifi/1.0/wifi_ap_iface.h new file mode 100644 index 0000000..98c5c9c --- /dev/null +++ b/wifi/1.0/wifi_ap_iface.h @@ -0,0 +1,80 @@ +/* + * 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_AP_IFACE_H_ +#define WIFI_AP_IFACE_H_ + +#include <android-base/macros.h> +#include <android/hardware/wifi/1.0/IWifiApIface.h> + +#include "wifi_feature_flags.h" +#include "wifi_iface_util.h" +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a AP Iface instance. + */ +class WifiApIface : public V1_0::IWifiApIface { + public: + WifiApIface( + const std::string& ifname, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util, + const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::string getName(); + + // HIDL methods exposed. + Return<void> getName(getName_cb hidl_status_cb) override; + Return<void> getType(getType_cb hidl_status_cb) override; + Return<void> setCountryCode(const hidl_array<int8_t, 2>& code, + setCountryCode_cb hidl_status_cb) override; + Return<void> getValidFrequenciesForBand( + WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair<WifiStatus, std::string> getNameInternal(); + std::pair<WifiStatus, IfaceType> getTypeInternal(); + WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code); + std::pair<WifiStatus, std::vector<WifiChannelInMhz>> + getValidFrequenciesForBandInternal(WifiBand band); + + std::string ifname_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_; + std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags_; + bool is_valid_; + + DISALLOW_COPY_AND_ASSIGN(WifiApIface); +}; + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_AP_IFACE_H_ diff --git a/wifi/1.0/wifi_chip.cpp b/wifi/1.0/wifi_chip.cpp new file mode 100644 index 0000000..e9991dc --- /dev/null +++ b/wifi/1.0/wifi_chip.cpp @@ -0,0 +1,1545 @@ +/* + * 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 <fcntl.h> + +#include <android-base/logging.h> +#include <android-base/unique_fd.h> +#include <cutils/properties.h> +#include <sys/stat.h> +#include <sys/sysmacros.h> + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_chip.h" +#include "wifi_status_util.h" + +namespace { +using android::sp; +using android::base::unique_fd; +using android::hardware::hidl_string; +using android::hardware::hidl_vec; +using android::hardware::wifi::V1_0::ChipModeId; +using android::hardware::wifi::V1_0::IfaceType; +using android::hardware::wifi::V1_0::IWifiChip; + +constexpr char kCpioMagic[] = "070701"; +constexpr size_t kMaxBufferSizeBytes = 1024 * 1024 * 3; +constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60 * 10; +constexpr uint32_t kMaxRingBufferFileNum = 20; +constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/"; +constexpr char kActiveWlanIfaceNameProperty[] = "wifi.active.interface"; +constexpr char kNoActiveWlanIfaceNamePropertyValue[] = ""; +constexpr unsigned kMaxWlanIfaces = 5; + +template <typename Iface> +void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) { + iface->invalidate(); + ifaces.erase(std::remove(ifaces.begin(), ifaces.end(), iface), + ifaces.end()); +} + +template <typename Iface> +void invalidateAndClearAll(std::vector<sp<Iface>>& ifaces) { + for (const auto& iface : ifaces) { + iface->invalidate(); + } + ifaces.clear(); +} + +template <typename Iface> +std::vector<hidl_string> getNames(std::vector<sp<Iface>>& ifaces) { + std::vector<hidl_string> names; + for (const auto& iface : ifaces) { + names.emplace_back(iface->getName()); + } + return names; +} + +template <typename Iface> +sp<Iface> findUsingName(std::vector<sp<Iface>>& ifaces, + const std::string& name) { + std::vector<hidl_string> names; + for (const auto& iface : ifaces) { + if (name == iface->getName()) { + return iface; + } + } + return nullptr; +} + +std::string getWlanIfaceName(unsigned idx) { + if (idx >= kMaxWlanIfaces) { + CHECK(false) << "Requested interface beyond wlan" << kMaxWlanIfaces; + return {}; + } + + std::array<char, PROPERTY_VALUE_MAX> buffer; + if (idx == 0 || idx == 1) { + const char* altPropName = + (idx == 0) ? "wifi.interface" : "wifi.concurrent.interface"; + auto res = property_get(altPropName, buffer.data(), nullptr); + if (res > 0) return buffer.data(); + } + std::string propName = "wifi.interface." + std::to_string(idx); + auto res = property_get(propName.c_str(), buffer.data(), nullptr); + if (res > 0) return buffer.data(); + + return "wlan" + std::to_string(idx); +} + +std::string getP2pIfaceName() { + std::array<char, PROPERTY_VALUE_MAX> buffer; + property_get("wifi.direct.interface", buffer.data(), "p2p0"); + return buffer.data(); +} + +void setActiveWlanIfaceNameProperty(const std::string& ifname) { + auto res = property_set(kActiveWlanIfaceNameProperty, ifname.data()); + if (res != 0) { + PLOG(ERROR) << "Failed to set active wlan iface name property"; + } +} + +// delete files that meet either conditions: +// 1. older than a predefined time in the wifi tombstone dir. +// 2. Files in excess to a predefined amount, starting from the oldest ones +bool removeOldFilesInternal() { + time_t now = time(0); + const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds; + std::unique_ptr<DIR, decltype(&closedir)> dir_dump( + opendir(kTombstoneFolderPath), closedir); + if (!dir_dump) { + PLOG(ERROR) << "Failed to open directory"; + return false; + } + struct dirent* dp; + bool success = true; + std::list<std::pair<const time_t, std::string>> valid_files; + while ((dp = readdir(dir_dump.get()))) { + if (dp->d_type != DT_REG) { + continue; + } + std::string cur_file_name(dp->d_name); + struct stat cur_file_stat; + std::string cur_file_path = kTombstoneFolderPath + cur_file_name; + if (stat(cur_file_path.c_str(), &cur_file_stat) == -1) { + PLOG(ERROR) << "Failed to get file stat for " << cur_file_path; + success = false; + continue; + } + const time_t cur_file_time = cur_file_stat.st_mtime; + valid_files.push_back( + std::pair<const time_t, std::string>(cur_file_time, cur_file_path)); + } + valid_files.sort(); // sort the list of files by last modified time from + // small to big. + uint32_t cur_file_count = valid_files.size(); + for (auto cur_file : valid_files) { + if (cur_file_count > kMaxRingBufferFileNum || + cur_file.first < delete_files_before) { + if (unlink(cur_file.second.c_str()) != 0) { + PLOG(ERROR) << "Error deleting file"; + success = false; + } + cur_file_count--; + } else { + break; + } + } + return success; +} + +// Helper function for |cpioArchiveFilesInDir| +bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name, + size_t file_name_len) { + std::array<char, 32 * 1024> read_buf; + ssize_t llen = + sprintf(read_buf.data(), + "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X", + kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid, + st.st_gid, static_cast<int>(st.st_nlink), + static_cast<int>(st.st_mtime), static_cast<int>(st.st_size), + major(st.st_dev), minor(st.st_dev), major(st.st_rdev), + minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0); + if (write(out_fd, read_buf.data(), llen) == -1) { + PLOG(ERROR) << "Error writing cpio header to file " << file_name; + return false; + } + if (write(out_fd, file_name, file_name_len) == -1) { + PLOG(ERROR) << "Error writing filename to file " << file_name; + return false; + } + + // NUL Pad header up to 4 multiple bytes. + llen = (llen + file_name_len) % 4; + if (llen != 0) { + const uint32_t zero = 0; + if (write(out_fd, &zero, 4 - llen) == -1) { + PLOG(ERROR) << "Error padding 0s to file " << file_name; + return false; + } + } + return true; +} + +// Helper function for |cpioArchiveFilesInDir| +size_t cpioWriteFileContent(int fd_read, int out_fd, struct stat& st) { + // writing content of file + std::array<char, 32 * 1024> read_buf; + ssize_t llen = st.st_size; + size_t n_error = 0; + while (llen > 0) { + ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size()); + if (bytes_read == -1) { + PLOG(ERROR) << "Error reading file"; + return ++n_error; + } + llen -= bytes_read; + if (write(out_fd, read_buf.data(), bytes_read) == -1) { + PLOG(ERROR) << "Error writing data to file"; + return ++n_error; + } + if (bytes_read == 0) { // this should never happen, but just in case + // to unstuck from while loop + PLOG(ERROR) << "Unexpected read result"; + n_error++; + break; + } + } + llen = st.st_size % 4; + if (llen != 0) { + const uint32_t zero = 0; + if (write(out_fd, &zero, 4 - llen) == -1) { + PLOG(ERROR) << "Error padding 0s to file"; + return ++n_error; + } + } + return n_error; +} + +// Helper function for |cpioArchiveFilesInDir| +bool cpioWriteFileTrailer(int out_fd) { + std::array<char, 4096> read_buf; + read_buf.fill(0); + if (write(out_fd, read_buf.data(), + sprintf(read_buf.data(), "070701%040X%056X%08XTRAILER!!!", 1, + 0x0b, 0) + + 4) == -1) { + PLOG(ERROR) << "Error writing trailing bytes"; + return false; + } + return true; +} + +// Archives all files in |input_dir| and writes result into |out_fd| +// Logic obtained from //external/toybox/toys/posix/cpio.c "Output cpio archive" +// portion +size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) { + struct dirent* dp; + size_t n_error = 0; + std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir), + closedir); + if (!dir_dump) { + PLOG(ERROR) << "Failed to open directory"; + return ++n_error; + } + while ((dp = readdir(dir_dump.get()))) { + if (dp->d_type != DT_REG) { + continue; + } + std::string cur_file_name(dp->d_name); + // string.size() does not include the null terminator. The cpio FreeBSD + // file header expects the null character to be included in the length. + const size_t file_name_len = cur_file_name.size() + 1; + struct stat st; + const std::string cur_file_path = kTombstoneFolderPath + cur_file_name; + if (stat(cur_file_path.c_str(), &st) == -1) { + PLOG(ERROR) << "Failed to get file stat for " << cur_file_path; + n_error++; + continue; + } + const int fd_read = open(cur_file_path.c_str(), O_RDONLY); + if (fd_read == -1) { + PLOG(ERROR) << "Failed to open file " << cur_file_path; + n_error++; + continue; + } + unique_fd file_auto_closer(fd_read); + if (!cpioWriteHeader(out_fd, st, cur_file_name.c_str(), + file_name_len)) { + return ++n_error; + } + size_t write_error = cpioWriteFileContent(fd_read, out_fd, st); + if (write_error) { + return n_error + write_error; + } + } + if (!cpioWriteFileTrailer(out_fd)) { + return ++n_error; + } + return n_error; +} + +// Helper function to create a non-const char*. +std::vector<char> makeCharVec(const std::string& str) { + std::vector<char> vec(str.size() + 1); + vec.assign(str.begin(), str.end()); + vec.push_back('\0'); + return vec; +} + +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using hidl_return_util::validateAndCall; +using hidl_return_util::validateAndCallWithLock; + +WifiChip::WifiChip( + ChipId chip_id, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<mode_controller::WifiModeController> mode_controller, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util, + const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags) + : chip_id_(chip_id), + legacy_hal_(legacy_hal), + mode_controller_(mode_controller), + iface_util_(iface_util), + feature_flags_(feature_flags), + is_valid_(true), + current_mode_id_(feature_flags::chip_mode_ids::kInvalid), + modes_(feature_flags.lock()->getChipModes()), + debug_ring_buffer_cb_registered_(false) { + setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue); +} + +void WifiChip::invalidate() { + if (!writeRingbufferFilesInternal()) { + LOG(ERROR) << "Error writing files to flash"; + } + invalidateAndRemoveAllIfaces(); + setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue); + legacy_hal_.reset(); + event_cb_handler_.invalidate(); + is_valid_ = false; +} + +bool WifiChip::isValid() { return is_valid_; } + +std::set<sp<V1_2::IWifiChipEventCallback>> WifiChip::getEventCallbacks() { + return event_cb_handler_.getCallbacks(); +} + +Return<void> WifiChip::getId(getId_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getIdInternal, hidl_status_cb); +} + +// Deprecated support for this callback +Return<void> WifiChip::registerEventCallback( + const sp<V1_0::IWifiChipEventCallback>& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::registerEventCallbackInternal, + hidl_status_cb, event_callback); +} + +Return<void> WifiChip::getCapabilities(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getCapabilitiesInternal, hidl_status_cb); +} + +Return<void> WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getAvailableModesInternal, + hidl_status_cb); +} + +Return<void> WifiChip::configureChip(ChipModeId mode_id, + configureChip_cb hidl_status_cb) { + return validateAndCallWithLock( + this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::configureChipInternal, hidl_status_cb, mode_id); +} + +Return<void> WifiChip::getMode(getMode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getModeInternal, hidl_status_cb); +} + +Return<void> WifiChip::requestChipDebugInfo( + requestChipDebugInfo_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::requestChipDebugInfoInternal, + hidl_status_cb); +} + +Return<void> WifiChip::requestDriverDebugDump( + requestDriverDebugDump_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::requestDriverDebugDumpInternal, + hidl_status_cb); +} + +Return<void> WifiChip::requestFirmwareDebugDump( + requestFirmwareDebugDump_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::requestFirmwareDebugDumpInternal, + hidl_status_cb); +} + +Return<void> WifiChip::createApIface(createApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createApIfaceInternal, hidl_status_cb); +} + +Return<void> WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getApIfaceNamesInternal, hidl_status_cb); +} + +Return<void> WifiChip::getApIface(const hidl_string& ifname, + getApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getApIfaceInternal, hidl_status_cb, + ifname); +} + +Return<void> WifiChip::removeApIface(const hidl_string& ifname, + removeApIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeApIfaceInternal, hidl_status_cb, + ifname); +} + +Return<void> WifiChip::createNanIface(createNanIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createNanIfaceInternal, hidl_status_cb); +} + +Return<void> WifiChip::getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getNanIfaceNamesInternal, hidl_status_cb); +} + +Return<void> WifiChip::getNanIface(const hidl_string& ifname, + getNanIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getNanIfaceInternal, hidl_status_cb, + ifname); +} + +Return<void> WifiChip::removeNanIface(const hidl_string& ifname, + removeNanIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeNanIfaceInternal, hidl_status_cb, + ifname); +} + +Return<void> WifiChip::createP2pIface(createP2pIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createP2pIfaceInternal, hidl_status_cb); +} + +Return<void> WifiChip::getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getP2pIfaceNamesInternal, hidl_status_cb); +} + +Return<void> WifiChip::getP2pIface(const hidl_string& ifname, + getP2pIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getP2pIfaceInternal, hidl_status_cb, + ifname); +} + +Return<void> WifiChip::removeP2pIface(const hidl_string& ifname, + removeP2pIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeP2pIfaceInternal, hidl_status_cb, + ifname); +} + +Return<void> WifiChip::createStaIface(createStaIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createStaIfaceInternal, hidl_status_cb); +} + +Return<void> WifiChip::getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getStaIfaceNamesInternal, hidl_status_cb); +} + +Return<void> WifiChip::getStaIface(const hidl_string& ifname, + getStaIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getStaIfaceInternal, hidl_status_cb, + ifname); +} + +Return<void> WifiChip::removeStaIface(const hidl_string& ifname, + removeStaIface_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::removeStaIfaceInternal, hidl_status_cb, + ifname); +} + +Return<void> WifiChip::createRttController( + const sp<IWifiIface>& bound_iface, createRttController_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::createRttControllerInternal, + hidl_status_cb, bound_iface); +} + +Return<void> WifiChip::getDebugRingBuffersStatus( + getDebugRingBuffersStatus_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getDebugRingBuffersStatusInternal, + hidl_status_cb); +} + +Return<void> WifiChip::startLoggingToDebugRingBuffer( + const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level, + uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes, + startLoggingToDebugRingBuffer_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::startLoggingToDebugRingBufferInternal, + hidl_status_cb, ring_name, verbose_level, + max_interval_in_sec, min_data_size_in_bytes); +} + +Return<void> WifiChip::forceDumpToDebugRingBuffer( + const hidl_string& ring_name, + forceDumpToDebugRingBuffer_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::forceDumpToDebugRingBufferInternal, + hidl_status_cb, ring_name); +} + +Return<void> WifiChip::flushRingBufferToFile( + flushRingBufferToFile_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::flushRingBufferToFileInternal, + hidl_status_cb); +} + +Return<void> WifiChip::stopLoggingToDebugRingBuffer( + stopLoggingToDebugRingBuffer_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::stopLoggingToDebugRingBufferInternal, + hidl_status_cb); +} + +Return<void> WifiChip::getDebugHostWakeReasonStats( + getDebugHostWakeReasonStats_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getDebugHostWakeReasonStatsInternal, + hidl_status_cb); +} + +Return<void> WifiChip::enableDebugErrorAlerts( + bool enable, enableDebugErrorAlerts_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::enableDebugErrorAlertsInternal, + hidl_status_cb, enable); +} + +Return<void> WifiChip::selectTxPowerScenario( + V1_1::IWifiChip::TxPowerScenario scenario, + selectTxPowerScenario_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::selectTxPowerScenarioInternal, + hidl_status_cb, scenario); +} + +Return<void> WifiChip::resetTxPowerScenario( + resetTxPowerScenario_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::resetTxPowerScenarioInternal, + hidl_status_cb); +} + +Return<void> WifiChip::setLatencyMode(LatencyMode mode, + setLatencyMode_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::setLatencyModeInternal, hidl_status_cb, + mode); +} + +Return<void> WifiChip::registerEventCallback_1_2( + const sp<V1_2::IWifiChipEventCallback>& event_callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::registerEventCallbackInternal_1_2, + hidl_status_cb, event_callback); +} + +Return<void> WifiChip::selectTxPowerScenario_1_2( + TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::selectTxPowerScenarioInternal_1_2, + hidl_status_cb, scenario); +} + +Return<void> WifiChip::getCapabilities_1_3(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, + &WifiChip::getCapabilitiesInternal_1_3, + hidl_status_cb); +} + +Return<void> WifiChip::debug(const hidl_handle& handle, + const hidl_vec<hidl_string>&) { + if (handle != nullptr && handle->numFds >= 1) { + int fd = handle->data[0]; + if (!writeRingbufferFilesInternal()) { + LOG(ERROR) << "Error writing files to flash"; + } + uint32_t n_error = cpioArchiveFilesInDir(fd, kTombstoneFolderPath); + if (n_error != 0) { + LOG(ERROR) << n_error << " errors occured in cpio function"; + } + fsync(fd); + } else { + LOG(ERROR) << "File handle error"; + } + return Void(); +} + +void WifiChip::invalidateAndRemoveAllIfaces() { + invalidateAndClearAll(ap_ifaces_); + invalidateAndClearAll(nan_ifaces_); + invalidateAndClearAll(p2p_ifaces_); + invalidateAndClearAll(sta_ifaces_); + // Since all the ifaces are invalid now, all RTT controller objects + // using those ifaces also need to be invalidated. + for (const auto& rtt : rtt_controllers_) { + rtt->invalidate(); + } + rtt_controllers_.clear(); +} + +void WifiChip::invalidateAndRemoveDependencies( + const std::string& removed_iface_name) { + for (const auto& nan_iface : nan_ifaces_) { + if (nan_iface->getName() == removed_iface_name) { + invalidateAndClear(nan_ifaces_, nan_iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback + ->onIfaceRemoved(IfaceType::NAN, removed_iface_name) + .isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + } + } + for (const auto& rtt : rtt_controllers_) { + if (rtt->getIfaceName() == removed_iface_name) { + invalidateAndClear(rtt_controllers_, rtt); + } + } +} + +std::pair<WifiStatus, ChipId> WifiChip::getIdInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_}; +} + +WifiStatus WifiChip::registerEventCallbackInternal( + const sp<V1_0::IWifiChipEventCallback>& /* event_callback */) { + // Deprecated support for this callback. + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal() { + // Deprecated support for this callback. + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0}; +} + +std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal_1_3() { + legacy_hal::wifi_error legacy_status; + uint32_t legacy_feature_set; + uint32_t legacy_logger_feature_set; + const auto ifname = getFirstActiveWlanIfaceName(); + std::tie(legacy_status, legacy_feature_set) = + legacy_hal_.lock()->getSupportedFeatureSet(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), 0}; + } + std::tie(legacy_status, legacy_logger_feature_set) = + legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + // some devices don't support querying logger feature set + legacy_logger_feature_set = 0; + } + uint32_t hidl_caps; + if (!hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities( + legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +std::pair<WifiStatus, std::vector<IWifiChip::ChipMode>> +WifiChip::getAvailableModesInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), modes_}; +} + +WifiStatus WifiChip::configureChipInternal( + /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, + ChipModeId mode_id) { + if (!isValidModeId(mode_id)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + if (mode_id == current_mode_id_) { + LOG(DEBUG) << "Already in the specified mode " << mode_id; + return createWifiStatus(WifiStatusCode::SUCCESS); + } + WifiStatus status = handleChipConfiguration(lock, mode_id); + if (status.code != WifiStatusCode::SUCCESS) { + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onChipReconfigureFailure(status).isOk()) { + LOG(ERROR) + << "Failed to invoke onChipReconfigureFailure callback"; + } + } + return status; + } + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onChipReconfigured(mode_id).isOk()) { + LOG(ERROR) << "Failed to invoke onChipReconfigured callback"; + } + } + current_mode_id_ = mode_id; + LOG(INFO) << "Configured chip in mode " << mode_id; + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return status; +} + +std::pair<WifiStatus, uint32_t> WifiChip::getModeInternal() { + if (!isValidModeId(current_mode_id_)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), + current_mode_id_}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_}; +} + +std::pair<WifiStatus, IWifiChip::ChipDebugInfo> +WifiChip::requestChipDebugInfoInternal() { + IWifiChip::ChipDebugInfo result; + legacy_hal::wifi_error legacy_status; + std::string driver_desc; + const auto ifname = getFirstActiveWlanIfaceName(); + std::tie(legacy_status, driver_desc) = + legacy_hal_.lock()->getDriverVersion(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get driver version: " + << legacyErrorToString(legacy_status); + WifiStatus status = createWifiStatusFromLegacyError( + legacy_status, "failed to get driver version"); + return {status, result}; + } + result.driverDescription = driver_desc.c_str(); + + std::string firmware_desc; + std::tie(legacy_status, firmware_desc) = + legacy_hal_.lock()->getFirmwareVersion(ifname); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get firmware version: " + << legacyErrorToString(legacy_status); + WifiStatus status = createWifiStatusFromLegacyError( + legacy_status, "failed to get firmware version"); + return {status, result}; + } + result.firmwareDescription = firmware_desc.c_str(); + + return {createWifiStatus(WifiStatusCode::SUCCESS), result}; +} + +std::pair<WifiStatus, std::vector<uint8_t>> +WifiChip::requestDriverDebugDumpInternal() { + legacy_hal::wifi_error legacy_status; + std::vector<uint8_t> driver_dump; + std::tie(legacy_status, driver_dump) = + legacy_hal_.lock()->requestDriverMemoryDump( + getFirstActiveWlanIfaceName()); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get driver debug dump: " + << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), + std::vector<uint8_t>()}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), driver_dump}; +} + +std::pair<WifiStatus, std::vector<uint8_t>> +WifiChip::requestFirmwareDebugDumpInternal() { + legacy_hal::wifi_error legacy_status; + std::vector<uint8_t> firmware_dump; + std::tie(legacy_status, firmware_dump) = + legacy_hal_.lock()->requestFirmwareMemoryDump( + getFirstActiveWlanIfaceName()); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to get firmware debug dump: " + << legacyErrorToString(legacy_status); + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump}; +} + +std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() { + if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string ifname = allocateApIfaceName(); + sp<WifiApIface> iface = + new WifiApIface(ifname, legacy_hal_, iface_util_, feature_flags_); + ap_ifaces_.push_back(iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair<WifiStatus, std::vector<hidl_string>> +WifiChip::getApIfaceNamesInternal() { + if (ap_ifaces_.empty()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(ap_ifaces_)}; +} + +std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::getApIfaceInternal( + const std::string& ifname) { + const auto iface = findUsingName(ap_ifaces_, ifname); + if (!iface.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(ap_ifaces_, ifname); + if (!iface.get()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + // Invalidate & remove any dependent objects first. + // Note: This is probably not required because we never create + // nan/rtt objects over AP iface. But, there is no harm to do it + // here and not make that assumption all over the place. + invalidateAndRemoveDependencies(ifname); + invalidateAndClear(ap_ifaces_, iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() { + if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::NAN)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + // These are still assumed to be based on wlan0. + std::string ifname = getFirstActiveWlanIfaceName(); + sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_, iface_util_); + nan_ifaces_.push_back(iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair<WifiStatus, std::vector<hidl_string>> +WifiChip::getNanIfaceNamesInternal() { + if (nan_ifaces_.empty()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(nan_ifaces_)}; +} + +std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::getNanIfaceInternal( + const std::string& ifname) { + const auto iface = findUsingName(nan_ifaces_, ifname); + if (!iface.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(nan_ifaces_, ifname); + if (!iface.get()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + invalidateAndClear(nan_ifaces_, iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::NAN, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::createP2pIfaceInternal() { + if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::P2P)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string ifname = getP2pIfaceName(); + sp<WifiP2pIface> iface = new WifiP2pIface(ifname, legacy_hal_); + p2p_ifaces_.push_back(iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair<WifiStatus, std::vector<hidl_string>> +WifiChip::getP2pIfaceNamesInternal() { + if (p2p_ifaces_.empty()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(p2p_ifaces_)}; +} + +std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::getP2pIfaceInternal( + const std::string& ifname) { + const auto iface = findUsingName(p2p_ifaces_, ifname); + if (!iface.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(p2p_ifaces_, ifname); + if (!iface.get()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + invalidateAndClear(p2p_ifaces_, iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() { + if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::STA)) { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + std::string ifname = allocateStaIfaceName(); + sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_, iface_util_); + sta_ifaces_.push_back(iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceAdded callback"; + } + } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +std::pair<WifiStatus, std::vector<hidl_string>> +WifiChip::getStaIfaceNamesInternal() { + if (sta_ifaces_.empty()) { + return {createWifiStatus(WifiStatusCode::SUCCESS), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)}; +} + +std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::getStaIfaceInternal( + const std::string& ifname) { + const auto iface = findUsingName(sta_ifaces_, ifname); + if (!iface.get()) { + return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), iface}; +} + +WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) { + const auto iface = findUsingName(sta_ifaces_, ifname); + if (!iface.get()) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + // Invalidate & remove any dependent objects first. + invalidateAndRemoveDependencies(ifname); + invalidateAndClear(sta_ifaces_, iface); + for (const auto& callback : event_cb_handler_.getCallbacks()) { + if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) { + LOG(ERROR) << "Failed to invoke onIfaceRemoved callback"; + } + } + setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName()); + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair<WifiStatus, sp<IWifiRttController>> +WifiChip::createRttControllerInternal(const sp<IWifiIface>& bound_iface) { + if (sta_ifaces_.size() == 0 && + !canCurrentModeSupportIfaceOfType(IfaceType::STA)) { + LOG(ERROR) << "createRttControllerInternal: Chip cannot support STAs " + "(and RTT by extension)"; + return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}}; + } + sp<WifiRttController> rtt = new WifiRttController( + getFirstActiveWlanIfaceName(), bound_iface, legacy_hal_); + rtt_controllers_.emplace_back(rtt); + return {createWifiStatus(WifiStatusCode::SUCCESS), rtt}; +} + +std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>> +WifiChip::getDebugRingBuffersStatusInternal() { + legacy_hal::wifi_error legacy_status; + std::vector<legacy_hal::wifi_ring_buffer_status> + legacy_ring_buffer_status_vec; + std::tie(legacy_status, legacy_ring_buffer_status_vec) = + legacy_hal_.lock()->getRingBuffersStatus(getFirstActiveWlanIfaceName()); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector<WifiDebugRingBufferStatus> hidl_ring_buffer_status_vec; + if (!hidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToHidl( + legacy_ring_buffer_status_vec, &hidl_ring_buffer_status_vec)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), + hidl_ring_buffer_status_vec}; +} + +WifiStatus WifiChip::startLoggingToDebugRingBufferInternal( + const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level, + uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes) { + WifiStatus status = registerDebugRingBufferCallback(); + if (status.code != WifiStatusCode::SUCCESS) { + return status; + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->startRingBufferLogging( + getFirstActiveWlanIfaceName(), ring_name, + static_cast< + std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>( + verbose_level), + max_interval_in_sec, min_data_size_in_bytes); + ringbuffer_map_.insert(std::pair<std::string, Ringbuffer>( + ring_name, Ringbuffer(kMaxBufferSizeBytes))); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::forceDumpToDebugRingBufferInternal( + const hidl_string& ring_name) { + WifiStatus status = registerDebugRingBufferCallback(); + if (status.code != WifiStatusCode::SUCCESS) { + return status; + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->getRingBufferData(getFirstActiveWlanIfaceName(), + ring_name); + + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::flushRingBufferToFileInternal() { + if (!writeRingbufferFilesInternal()) { + LOG(ERROR) << "Error writing files to flash"; + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->deregisterRingBufferCallbackHandler( + getFirstActiveWlanIfaceName()); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, WifiDebugHostWakeReasonStats> +WifiChip::getDebugHostWakeReasonStatsInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::WakeReasonStats legacy_stats; + std::tie(legacy_status, legacy_stats) = + legacy_hal_.lock()->getWakeReasonStats(getFirstActiveWlanIfaceName()); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + WifiDebugHostWakeReasonStats hidl_stats; + if (!hidl_struct_util::convertLegacyWakeReasonStatsToHidl(legacy_stats, + &hidl_stats)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats}; +} + +WifiStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) { + legacy_hal::wifi_error legacy_status; + if (enable) { + android::wp<WifiChip> weak_ptr_this(this); + const auto& on_alert_callback = [weak_ptr_this]( + int32_t error_code, + std::vector<uint8_t> debug_data) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onDebugErrorAlert(error_code, debug_data) + .isOk()) { + LOG(ERROR) << "Failed to invoke onDebugErrorAlert callback"; + } + } + }; + legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler( + getFirstActiveWlanIfaceName(), on_alert_callback); + } else { + legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler( + getFirstActiveWlanIfaceName()); + } + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::selectTxPowerScenarioInternal( + V1_1::IWifiChip::TxPowerScenario scenario) { + auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario( + getFirstActiveWlanIfaceName(), + hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::resetTxPowerScenarioInternal() { + auto legacy_status = + legacy_hal_.lock()->resetTxPowerScenario(getFirstActiveWlanIfaceName()); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::setLatencyModeInternal(LatencyMode mode) { + auto legacy_status = legacy_hal_.lock()->setLatencyMode( + getFirstActiveWlanIfaceName(), + hidl_struct_util::convertHidlLatencyModeToLegacy(mode)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::registerEventCallbackInternal_1_2( + const sp<V1_2::IWifiChipEventCallback>& event_callback) { + if (!event_cb_handler_.addCallback(event_callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2( + TxPowerScenario scenario) { + auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario( + getFirstActiveWlanIfaceName(), + hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::handleChipConfiguration( + /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, + ChipModeId mode_id) { + // If the chip is already configured in a different mode, stop + // the legacy HAL and then start it after firmware mode change. + if (isValidModeId(current_mode_id_)) { + LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_ + << " to mode " << mode_id; + invalidateAndRemoveAllIfaces(); + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->stop(lock, []() {}); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to stop legacy HAL: " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + } + // Firmware mode change not needed for V2 devices. + bool success = true; + if (mode_id == feature_flags::chip_mode_ids::kV1Sta) { + success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA); + } else if (mode_id == feature_flags::chip_mode_ids::kV1Ap) { + success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP); + } + if (!success) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start(); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to start legacy HAL: " + << legacyErrorToString(legacy_status); + return createWifiStatusFromLegacyError(legacy_status); + } + // Every time the HAL is restarted, we need to register the + // radio mode change callback. + WifiStatus status = registerRadioModeChangeCallback(); + if (status.code != WifiStatusCode::SUCCESS) { + // This probably is not a critical failure? + LOG(ERROR) << "Failed to register radio mode change callback"; + } + // Extract and save the version information into property. + std::pair<WifiStatus, IWifiChip::ChipDebugInfo> version_info; + version_info = WifiChip::requestChipDebugInfoInternal(); + if (WifiStatusCode::SUCCESS == version_info.first.code) { + property_set("vendor.wlan.firmware.version", + version_info.second.firmwareDescription.c_str()); + property_set("vendor.wlan.driver.version", + version_info.second.driverDescription.c_str()); + } + + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiChip::registerDebugRingBufferCallback() { + if (debug_ring_buffer_cb_registered_) { + return createWifiStatus(WifiStatusCode::SUCCESS); + } + + android::wp<WifiChip> weak_ptr_this(this); + const auto& on_ring_buffer_data_callback = + [weak_ptr_this](const std::string& name, + const std::vector<uint8_t>& data, + const legacy_hal::wifi_ring_buffer_status& status) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiDebugRingBufferStatus hidl_status; + if (!hidl_struct_util::convertLegacyDebugRingBufferStatusToHidl( + status, &hidl_status)) { + LOG(ERROR) << "Error converting ring buffer status"; + return; + } + const auto& target = shared_ptr_this->ringbuffer_map_.find(name); + if (target != shared_ptr_this->ringbuffer_map_.end()) { + Ringbuffer& cur_buffer = target->second; + cur_buffer.append(data); + } else { + LOG(ERROR) << "Ringname " << name << " not found"; + return; + } + }; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->registerRingBufferCallbackHandler( + getFirstActiveWlanIfaceName(), on_ring_buffer_data_callback); + + if (legacy_status == legacy_hal::WIFI_SUCCESS) { + debug_ring_buffer_cb_registered_ = true; + } + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiChip::registerRadioModeChangeCallback() { + android::wp<WifiChip> weak_ptr_this(this); + const auto& on_radio_mode_change_callback = + [weak_ptr_this](const std::vector<legacy_hal::WifiMacInfo>& mac_infos) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo> + hidl_radio_mode_infos; + if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl( + mac_infos, &hidl_radio_mode_infos)) { + LOG(ERROR) << "Error converting wifi mac info"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onRadioModeChange(hidl_radio_mode_infos) + .isOk()) { + LOG(ERROR) << "Failed to invoke onRadioModeChange" + << " callback on: " << toString(callback); + } + } + }; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->registerRadioModeChangeCallbackHandler( + getFirstActiveWlanIfaceName(), on_radio_mode_change_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::vector<IWifiChip::ChipIfaceCombination> +WifiChip::getCurrentModeIfaceCombinations() { + if (!isValidModeId(current_mode_id_)) { + LOG(ERROR) << "Chip not configured in a mode yet"; + return {}; + } + for (const auto& mode : modes_) { + if (mode.id == current_mode_id_) { + return mode.availableCombinations; + } + } + CHECK(0) << "Expected to find iface combinations for current mode!"; + return {}; +} + +// Returns a map indexed by IfaceType with the number of ifaces currently +// created of the corresponding type. +std::map<IfaceType, size_t> WifiChip::getCurrentIfaceCombination() { + std::map<IfaceType, size_t> iface_counts; + iface_counts[IfaceType::AP] = ap_ifaces_.size(); + iface_counts[IfaceType::NAN] = nan_ifaces_.size(); + iface_counts[IfaceType::P2P] = p2p_ifaces_.size(); + iface_counts[IfaceType::STA] = sta_ifaces_.size(); + return iface_counts; +} + +// This expands the provided iface combinations to a more parseable +// form. Returns a vector of available combinations possible with the number +// of ifaces of each type in the combination. +// This method is a port of HalDeviceManager.expandIfaceCombos() from framework. +std::vector<std::map<IfaceType, size_t>> WifiChip::expandIfaceCombinations( + const IWifiChip::ChipIfaceCombination& combination) { + uint32_t num_expanded_combos = 1; + for (const auto& limit : combination.limits) { + for (uint32_t i = 0; i < limit.maxIfaces; i++) { + num_expanded_combos *= limit.types.size(); + } + } + + // Allocate the vector of expanded combos and reset all iface counts to 0 + // in each combo. + std::vector<std::map<IfaceType, size_t>> expanded_combos; + expanded_combos.resize(num_expanded_combos); + for (auto& expanded_combo : expanded_combos) { + for (const auto type : + {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) { + expanded_combo[type] = 0; + } + } + uint32_t span = num_expanded_combos; + for (const auto& limit : combination.limits) { + for (uint32_t i = 0; i < limit.maxIfaces; i++) { + span /= limit.types.size(); + for (uint32_t k = 0; k < num_expanded_combos; ++k) { + const auto iface_type = + limit.types[(k / span) % limit.types.size()]; + expanded_combos[k][iface_type]++; + } + } + } + return expanded_combos; +} + +bool WifiChip::canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces( + const std::map<IfaceType, size_t>& expanded_combo, + IfaceType requested_type) { + const auto current_combo = getCurrentIfaceCombination(); + + // Check if we have space for 1 more iface of |type| in this combo + for (const auto type : + {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) { + size_t num_ifaces_needed = current_combo.at(type); + if (type == requested_type) { + num_ifaces_needed++; + } + size_t num_ifaces_allowed = expanded_combo.at(type); + if (num_ifaces_needed > num_ifaces_allowed) { + return false; + } + } + return true; +} + +// This method does the following: +// a) Enumerate all possible iface combos by expanding the current +// ChipIfaceCombination. +// b) Check if the requested iface type can be added to the current mode +// with the iface combination that is already active. +bool WifiChip::canCurrentModeSupportIfaceOfTypeWithCurrentIfaces( + IfaceType requested_type) { + if (!isValidModeId(current_mode_id_)) { + LOG(ERROR) << "Chip not configured in a mode yet"; + return false; + } + const auto combinations = getCurrentModeIfaceCombinations(); + for (const auto& combination : combinations) { + const auto expanded_combos = expandIfaceCombinations(combination); + for (const auto& expanded_combo : expanded_combos) { + if (canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces( + expanded_combo, requested_type)) { + return true; + } + } + } + return false; +} + +// Note: This does not consider ifaces already active. It only checks if the +// provided expanded iface combination can support the requested combo. +bool WifiChip::canExpandedIfaceComboSupportIfaceCombo( + const std::map<IfaceType, size_t>& expanded_combo, + const std::map<IfaceType, size_t>& req_combo) { + // Check if we have space for 1 more iface of |type| in this combo + for (const auto type : + {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) { + if (req_combo.count(type) == 0) { + // Iface of "type" not in the req_combo. + continue; + } + size_t num_ifaces_needed = req_combo.at(type); + size_t num_ifaces_allowed = expanded_combo.at(type); + if (num_ifaces_needed > num_ifaces_allowed) { + return false; + } + } + return true; +} +// This method does the following: +// a) Enumerate all possible iface combos by expanding the current +// ChipIfaceCombination. +// b) Check if the requested iface combo can be added to the current mode. +// Note: This does not consider ifaces already active. It only checks if the +// current mode can support the requested combo. +bool WifiChip::canCurrentModeSupportIfaceCombo( + const std::map<IfaceType, size_t>& req_combo) { + if (!isValidModeId(current_mode_id_)) { + LOG(ERROR) << "Chip not configured in a mode yet"; + return false; + } + const auto combinations = getCurrentModeIfaceCombinations(); + for (const auto& combination : combinations) { + const auto expanded_combos = expandIfaceCombinations(combination); + for (const auto& expanded_combo : expanded_combos) { + if (canExpandedIfaceComboSupportIfaceCombo(expanded_combo, + req_combo)) { + return true; + } + } + } + return false; +} + +// This method does the following: +// a) Enumerate all possible iface combos by expanding the current +// ChipIfaceCombination. +// b) Check if the requested iface type can be added to the current mode. +bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType requested_type) { + // Check if we can support atleast 1 iface of type. + std::map<IfaceType, size_t> req_iface_combo; + req_iface_combo[requested_type] = 1; + return canCurrentModeSupportIfaceCombo(req_iface_combo); +} + +bool WifiChip::isValidModeId(ChipModeId mode_id) { + for (const auto& mode : modes_) { + if (mode.id == mode_id) { + return true; + } + } + return false; +} + +bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() { + // Check if we can support atleast 1 STA & 1 AP concurrently. + std::map<IfaceType, size_t> req_iface_combo; + req_iface_combo[IfaceType::AP] = 1; + req_iface_combo[IfaceType::STA] = 1; + return canCurrentModeSupportIfaceCombo(req_iface_combo); +} + +bool WifiChip::isDualApAllowedInCurrentMode() { + // Check if we can support atleast 1 STA & 1 AP concurrently. + std::map<IfaceType, size_t> req_iface_combo; + req_iface_combo[IfaceType::AP] = 2; + return canCurrentModeSupportIfaceCombo(req_iface_combo); +} + +std::string WifiChip::getFirstActiveWlanIfaceName() { + if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName(); + if (ap_ifaces_.size() > 0) return ap_ifaces_[0]->getName(); + // This could happen if the chip call is made before any STA/AP + // iface is created. Default to wlan0 for such cases. + LOG(WARNING) << "No active wlan interfaces in use! Using default"; + return getWlanIfaceName(0); +} + +// Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx| +// not already in use. +// Note: This doesn't check the actual presence of these interfaces. +std::string WifiChip::allocateApOrStaIfaceName(uint32_t start_idx) { + for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) { + const auto ifname = getWlanIfaceName(idx); + if (findUsingName(ap_ifaces_, ifname)) continue; + if (findUsingName(sta_ifaces_, ifname)) continue; + return ifname; + } + // This should never happen. We screwed up somewhere if it did. + CHECK(false) << "All wlan interfaces in use already!"; + return {}; +} + +// AP iface names start with idx 1 for modes supporting +// concurrent STA and not dual AP, else start with idx 0. +std::string WifiChip::allocateApIfaceName() { + return allocateApOrStaIfaceName((isStaApConcurrencyAllowedInCurrentMode() && + !isDualApAllowedInCurrentMode()) + ? 1 + : 0); +} + +// STA iface names start with idx 0. +// Primary STA iface will always be 0. +std::string WifiChip::allocateStaIfaceName() { + return allocateApOrStaIfaceName(0); +} + +bool WifiChip::writeRingbufferFilesInternal() { + if (!removeOldFilesInternal()) { + LOG(ERROR) << "Error occurred while deleting old tombstone files"; + return false; + } + // write ringbuffers to file + for (const auto& item : ringbuffer_map_) { + const Ringbuffer& cur_buffer = item.second; + if (cur_buffer.getData().empty()) { + continue; + } + const std::string file_path_raw = + kTombstoneFolderPath + item.first + "XXXXXXXXXX"; + const int dump_fd = mkstemp(makeCharVec(file_path_raw).data()); + if (dump_fd == -1) { + PLOG(ERROR) << "create file failed"; + return false; + } + unique_fd file_auto_closer(dump_fd); + for (const auto& cur_block : cur_buffer.getData()) { + if (write(dump_fd, cur_block.data(), + sizeof(cur_block[0]) * cur_block.size()) == -1) { + PLOG(ERROR) << "Error writing to file"; + } + } + } + return true; +} + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi_chip.h b/wifi/1.0/wifi_chip.h new file mode 100644 index 0000000..153ca6a --- /dev/null +++ b/wifi/1.0/wifi_chip.h @@ -0,0 +1,281 @@ +/* + * 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 <list> +#include <map> + +#include <android-base/macros.h> +#include <android/hardware/wifi/1.3/IWifiChip.h> + +#include "hidl_callback_util.h" +#include "ringbuffer.h" +#include "wifi_ap_iface.h" +#include "wifi_feature_flags.h" +#include "wifi_legacy_hal.h" +#include "wifi_mode_controller.h" +#include "wifi_nan_iface.h" +#include "wifi_p2p_iface.h" +#include "wifi_rtt_controller.h" +#include "wifi_sta_iface.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * 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 V1_3::IWifiChip { + public: + WifiChip( + ChipId chip_id, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<mode_controller::WifiModeController> + mode_controller, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util, + const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags); + // HIDL does not provide a built-in mechanism to let the server invalidate + // a HIDL interface object after creation. If any client process holds onto + // a reference to the object in their context, any method calls on that + // reference will continue to be directed to the server. + // + // However Wifi HAL needs to control the lifetime of these objects. So, add + // a public |invalidate| method to |WifiChip| and it's child objects. This + // will be used to mark an object invalid when either: + // a) Wifi HAL is stopped, or + // b) Wifi Chip is reconfigured. + // + // All HIDL method implementations should check if the object is still + // marked valid before processing them. + void invalidate(); + bool isValid(); + std::set<sp<V1_2::IWifiChipEventCallback>> getEventCallbacks(); + + // HIDL methods exposed. + Return<void> getId(getId_cb hidl_status_cb) override; + // Deprecated support for this callback + Return<void> registerEventCallback( + const sp<V1_0::IWifiChipEventCallback>& event_callback, + registerEventCallback_cb hidl_status_cb) override; + Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override; + Return<void> getAvailableModes( + getAvailableModes_cb hidl_status_cb) override; + Return<void> configureChip(ChipModeId mode_id, + configureChip_cb hidl_status_cb) override; + Return<void> getMode(getMode_cb hidl_status_cb) override; + Return<void> requestChipDebugInfo( + requestChipDebugInfo_cb hidl_status_cb) override; + Return<void> requestDriverDebugDump( + requestDriverDebugDump_cb hidl_status_cb) override; + Return<void> requestFirmwareDebugDump( + requestFirmwareDebugDump_cb hidl_status_cb) override; + Return<void> createApIface(createApIface_cb hidl_status_cb) override; + Return<void> getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override; + Return<void> getApIface(const hidl_string& ifname, + getApIface_cb hidl_status_cb) override; + Return<void> removeApIface(const hidl_string& ifname, + removeApIface_cb hidl_status_cb) override; + Return<void> createNanIface(createNanIface_cb hidl_status_cb) override; + Return<void> getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override; + Return<void> getNanIface(const hidl_string& ifname, + getNanIface_cb hidl_status_cb) override; + Return<void> removeNanIface(const hidl_string& ifname, + removeNanIface_cb hidl_status_cb) override; + Return<void> createP2pIface(createP2pIface_cb hidl_status_cb) override; + Return<void> getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) override; + Return<void> getP2pIface(const hidl_string& ifname, + getP2pIface_cb hidl_status_cb) override; + Return<void> removeP2pIface(const hidl_string& ifname, + removeP2pIface_cb hidl_status_cb) override; + Return<void> createStaIface(createStaIface_cb hidl_status_cb) override; + Return<void> getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) override; + Return<void> getStaIface(const hidl_string& ifname, + getStaIface_cb hidl_status_cb) override; + Return<void> removeStaIface(const hidl_string& ifname, + removeStaIface_cb hidl_status_cb) override; + Return<void> createRttController( + const sp<IWifiIface>& bound_iface, + createRttController_cb hidl_status_cb) override; + Return<void> getDebugRingBuffersStatus( + getDebugRingBuffersStatus_cb hidl_status_cb) override; + Return<void> startLoggingToDebugRingBuffer( + const hidl_string& ring_name, + WifiDebugRingBufferVerboseLevel verbose_level, + uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes, + startLoggingToDebugRingBuffer_cb hidl_status_cb) override; + Return<void> forceDumpToDebugRingBuffer( + const hidl_string& ring_name, + forceDumpToDebugRingBuffer_cb hidl_status_cb) override; + Return<void> flushRingBufferToFile( + flushRingBufferToFile_cb hidl_status_cb) override; + Return<void> stopLoggingToDebugRingBuffer( + stopLoggingToDebugRingBuffer_cb hidl_status_cb) override; + Return<void> getDebugHostWakeReasonStats( + getDebugHostWakeReasonStats_cb hidl_status_cb) override; + Return<void> enableDebugErrorAlerts( + bool enable, enableDebugErrorAlerts_cb hidl_status_cb) override; + Return<void> selectTxPowerScenario( + V1_1::IWifiChip::TxPowerScenario scenario, + selectTxPowerScenario_cb hidl_status_cb) override; + Return<void> resetTxPowerScenario( + resetTxPowerScenario_cb hidl_status_cb) override; + Return<void> setLatencyMode(LatencyMode mode, + setLatencyMode_cb hidl_status_cb) override; + Return<void> registerEventCallback_1_2( + const sp<V1_2::IWifiChipEventCallback>& event_callback, + registerEventCallback_1_2_cb hidl_status_cb) override; + Return<void> selectTxPowerScenario_1_2( + TxPowerScenario scenario, + selectTxPowerScenario_cb hidl_status_cb) override; + Return<void> getCapabilities_1_3( + getCapabilities_cb hidl_status_cb) override; + Return<void> debug(const hidl_handle& handle, + const hidl_vec<hidl_string>& options) override; + + private: + void invalidateAndRemoveAllIfaces(); + // When a STA iface is removed any dependent NAN-ifaces/RTT-controllers are + // invalidated & removed. + void invalidateAndRemoveDependencies(const std::string& removed_iface_name); + + // Corresponding worker functions for the HIDL methods. + std::pair<WifiStatus, ChipId> getIdInternal(); + // Deprecated support for this callback + WifiStatus registerEventCallbackInternal( + const sp<V1_0::IWifiChipEventCallback>& event_callback); + std::pair<WifiStatus, uint32_t> getCapabilitiesInternal(); + std::pair<WifiStatus, std::vector<ChipMode>> getAvailableModesInternal(); + WifiStatus configureChipInternal( + std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id); + std::pair<WifiStatus, uint32_t> getModeInternal(); + std::pair<WifiStatus, IWifiChip::ChipDebugInfo> + requestChipDebugInfoInternal(); + std::pair<WifiStatus, std::vector<uint8_t>> + requestDriverDebugDumpInternal(); + std::pair<WifiStatus, std::vector<uint8_t>> + requestFirmwareDebugDumpInternal(); + std::pair<WifiStatus, sp<IWifiApIface>> createApIfaceInternal(); + std::pair<WifiStatus, std::vector<hidl_string>> getApIfaceNamesInternal(); + std::pair<WifiStatus, sp<IWifiApIface>> getApIfaceInternal( + const std::string& ifname); + WifiStatus removeApIfaceInternal(const std::string& ifname); + std::pair<WifiStatus, sp<IWifiNanIface>> createNanIfaceInternal(); + std::pair<WifiStatus, std::vector<hidl_string>> getNanIfaceNamesInternal(); + std::pair<WifiStatus, sp<IWifiNanIface>> getNanIfaceInternal( + const std::string& ifname); + WifiStatus removeNanIfaceInternal(const std::string& ifname); + std::pair<WifiStatus, sp<IWifiP2pIface>> createP2pIfaceInternal(); + std::pair<WifiStatus, std::vector<hidl_string>> getP2pIfaceNamesInternal(); + std::pair<WifiStatus, sp<IWifiP2pIface>> getP2pIfaceInternal( + const std::string& ifname); + WifiStatus removeP2pIfaceInternal(const std::string& ifname); + std::pair<WifiStatus, sp<IWifiStaIface>> createStaIfaceInternal(); + std::pair<WifiStatus, std::vector<hidl_string>> getStaIfaceNamesInternal(); + std::pair<WifiStatus, sp<IWifiStaIface>> getStaIfaceInternal( + const std::string& ifname); + WifiStatus removeStaIfaceInternal(const std::string& ifname); + std::pair<WifiStatus, sp<IWifiRttController>> createRttControllerInternal( + const sp<IWifiIface>& bound_iface); + std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>> + getDebugRingBuffersStatusInternal(); + WifiStatus startLoggingToDebugRingBufferInternal( + const hidl_string& ring_name, + WifiDebugRingBufferVerboseLevel verbose_level, + uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes); + WifiStatus forceDumpToDebugRingBufferInternal(const hidl_string& ring_name); + WifiStatus flushRingBufferToFileInternal(); + WifiStatus stopLoggingToDebugRingBufferInternal(); + std::pair<WifiStatus, WifiDebugHostWakeReasonStats> + getDebugHostWakeReasonStatsInternal(); + WifiStatus enableDebugErrorAlertsInternal(bool enable); + WifiStatus selectTxPowerScenarioInternal( + V1_1::IWifiChip::TxPowerScenario scenario); + WifiStatus resetTxPowerScenarioInternal(); + WifiStatus setLatencyModeInternal(LatencyMode mode); + WifiStatus registerEventCallbackInternal_1_2( + const sp<V1_2::IWifiChipEventCallback>& event_callback); + WifiStatus selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario); + std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_3(); + WifiStatus handleChipConfiguration( + std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id); + WifiStatus registerDebugRingBufferCallback(); + WifiStatus registerRadioModeChangeCallback(); + + std::vector<IWifiChip::ChipIfaceCombination> + getCurrentModeIfaceCombinations(); + std::map<IfaceType, size_t> getCurrentIfaceCombination(); + std::vector<std::map<IfaceType, size_t>> expandIfaceCombinations( + const IWifiChip::ChipIfaceCombination& combination); + bool canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces( + const std::map<IfaceType, size_t>& expanded_combo, + IfaceType requested_type); + bool canCurrentModeSupportIfaceOfTypeWithCurrentIfaces( + IfaceType requested_type); + bool canExpandedIfaceComboSupportIfaceCombo( + const std::map<IfaceType, size_t>& expanded_combo, + const std::map<IfaceType, size_t>& req_combo); + bool canCurrentModeSupportIfaceCombo( + const std::map<IfaceType, size_t>& req_combo); + bool canCurrentModeSupportIfaceOfType(IfaceType requested_type); + bool isValidModeId(ChipModeId mode_id); + bool isStaApConcurrencyAllowedInCurrentMode(); + bool isDualApAllowedInCurrentMode(); + std::string getFirstActiveWlanIfaceName(); + std::string allocateApOrStaIfaceName(uint32_t start_idx); + std::string allocateApIfaceName(); + std::string allocateStaIfaceName(); + bool writeRingbufferFilesInternal(); + + ChipId chip_id_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + std::weak_ptr<mode_controller::WifiModeController> mode_controller_; + std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_; + std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags_; + std::vector<sp<WifiApIface>> ap_ifaces_; + std::vector<sp<WifiNanIface>> nan_ifaces_; + std::vector<sp<WifiP2pIface>> p2p_ifaces_; + std::vector<sp<WifiStaIface>> sta_ifaces_; + std::vector<sp<WifiRttController>> rtt_controllers_; + std::map<std::string, Ringbuffer> ringbuffer_map_; + bool is_valid_; + // Members pertaining to chip configuration. + uint32_t current_mode_id_; + std::vector<IWifiChip::ChipMode> modes_; + // The legacy ring buffer callback API has only a global callback + // registration mechanism. Use this to check if we have already + // registered a callback. + bool debug_ring_buffer_cb_registered_; + hidl_callback_util::HidlCallbackHandler<V1_2::IWifiChipEventCallback> + event_cb_handler_; + + DISALLOW_COPY_AND_ASSIGN(WifiChip); +}; + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_CHIP_H_ diff --git a/wifi/1.0/wifi_feature_flags.cpp b/wifi/1.0/wifi_feature_flags.cpp new file mode 100644 index 0000000..7212cfa --- /dev/null +++ b/wifi/1.0/wifi_feature_flags.cpp @@ -0,0 +1,168 @@ +/* + * 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_feature_flags.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace feature_flags { + +using V1_0::ChipModeId; +using V1_0::IfaceType; +using V1_0::IWifiChip; + +/* The chip may either have a single mode supporting any number of combinations, + * or a fixed dual-mode (so it involves firmware loading to switch between + * modes) setting. If there is a need to support more modes, it needs to be + * implemented manually in WiFi HAL (see changeFirmwareMode in + * WifiChip::handleChipConfiguration). + * + * Supported combinations are defined in device's makefile, for example: + * WIFI_HAL_INTERFACE_COMBINATIONS := {{{STA, AP}, 1}, {{P2P, NAN}, 1}}, + * WIFI_HAL_INTERFACE_COMBINATIONS += {{{STA}, 1}, {{AP}, 2}} + * What means: + * Interface combination 1: 1 STA or AP and 1 P2P or NAN concurrent iface + * operations. + * Interface combination 2: 1 STA and 2 AP concurrent iface operations. + * + * For backward compatibility, the following makefile flags can be used to + * generate combinations list: + * - WIFI_HIDL_FEATURE_DUAL_INTERFACE + * - WIFI_HIDL_FEATURE_DISABLE_AP + * - WIFI_HIDL_FEATURE_AWARE + * However, they are ignored if WIFI_HAL_INTERFACE_COMBINATIONS was provided. + * With WIFI_HIDL_FEATURE_DUAL_INTERFACE flag set, there is a single mode with + * two interface combinations: + * Interface Combination 1: Will support 1 STA and 1 P2P or NAN (optional) + * concurrent iface operations. + * Interface Combination 2: Will support 1 STA and 1 AP concurrent + * iface operations. + * + * The only dual-mode configuration supported is for alternating STA and AP + * mode, that may involve firmware reloading. In such case, there are 2 separate + * modes of operation with 1 interface combination each: + * Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN (optional) + * concurrent iface operations. + * Mode 2 (AP mode): Will support 1 AP iface operation. + * + * If Aware is enabled, the iface combination will be modified to support either + * P2P or NAN in place of just P2P. + */ +// clang-format off +#ifdef WIFI_HAL_INTERFACE_COMBINATIONS +constexpr ChipModeId kMainModeId = chip_mode_ids::kV3; +#elif defined(WIFI_HIDL_FEATURE_DUAL_INTERFACE) +// former V2 (fixed dual interface) setup expressed as V3 +constexpr ChipModeId kMainModeId = chip_mode_ids::kV3; +# ifdef WIFI_HIDL_FEATURE_DISABLE_AP +# ifdef WIFI_HIDL_FEATURE_AWARE +// 1 STA + 1 of (P2P or NAN) +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}} +# else +// 1 STA + 1 P2P +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}} +# endif +# else +# ifdef WIFI_HIDL_FEATURE_AWARE +// (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN)) +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\ + {{{STA}, 1}, {{P2P, NAN}, 1}} +# else +// (1 STA + 1 AP) or (1 STA + 1 P2P) +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\ + {{{STA}, 1}, {{P2P}, 1}} +# endif +# endif +#else +// V1 (fixed single interface, dual-mode chip) +constexpr ChipModeId kMainModeId = chip_mode_ids::kV1Sta; +# ifdef WIFI_HIDL_FEATURE_AWARE +// 1 STA + 1 of (P2P or NAN) +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}} +# else +// 1 STA + 1 P2P +# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}} +# endif + +# ifndef WIFI_HIDL_FEATURE_DISABLE_AP +# define WIFI_HAL_INTERFACE_COMBINATIONS_AP {{{AP}, 1}} +# endif +#endif +// clang-format on + +/** + * Helper class to convert a collection of combination limits to a combination. + * + * The main point here is to simplify the syntax required by + * WIFI_HAL_INTERFACE_COMBINATIONS. + */ +struct ChipIfaceCombination + : public hidl_vec<IWifiChip::ChipIfaceCombinationLimit> { + ChipIfaceCombination( + const std::initializer_list<IWifiChip::ChipIfaceCombinationLimit> list) + : hidl_vec(list) {} + + operator IWifiChip::ChipIfaceCombination() const { return {*this}; } + + static hidl_vec<IWifiChip::ChipIfaceCombination> make_vec( + const std::initializer_list<ChipIfaceCombination> list) { + return hidl_vec<IWifiChip::ChipIfaceCombination>( // + std::begin(list), std::end(list)); + } +}; + +#define STA IfaceType::STA +#define AP IfaceType::AP +#define P2P IfaceType::P2P +#define NAN IfaceType::NAN +static const std::vector<IWifiChip::ChipMode> kChipModes{ + {kMainModeId, + ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS})}, +#ifdef WIFI_HAL_INTERFACE_COMBINATIONS_AP + {chip_mode_ids::kV1Ap, + ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_AP})}, +#endif +}; +#undef STA +#undef AP +#undef P2P +#undef NAN + +#ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION +static const bool wifiHidlFeatureDisableApMacRandomization = true; +#else +static const bool wifiHidlFeatureDisableApMacRandomization = false; +#endif // WIFI_HIDL_FEATURE_DISABLE_AP + +WifiFeatureFlags::WifiFeatureFlags() {} + +std::vector<IWifiChip::ChipMode> WifiFeatureFlags::getChipModes() { + return kChipModes; +} + +bool WifiFeatureFlags::isApMacRandomizationDisabled() { + return wifiHidlFeatureDisableApMacRandomization; +} + +} // namespace feature_flags +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi_feature_flags.h b/wifi/1.0/wifi_feature_flags.h new file mode 100644 index 0000000..3ae6920 --- /dev/null +++ b/wifi/1.0/wifi_feature_flags.h @@ -0,0 +1,56 @@ +/* + * 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_FEATURE_FLAGS_H_ +#define WIFI_FEATURE_FLAGS_H_ + +#include <android/hardware/wifi/1.2/IWifiChip.h> + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace feature_flags { + +namespace chip_mode_ids { +// These mode ID's should be unique (even across combo versions). Refer to +// handleChipConfiguration() for it's usage. +constexpr V1_0::ChipModeId kInvalid = UINT32_MAX; +// Mode ID's for V1 +constexpr V1_0::ChipModeId kV1Sta = 0; +constexpr V1_0::ChipModeId kV1Ap = 1; +// Mode ID for V3 +constexpr V1_0::ChipModeId kV3 = 3; +} // namespace chip_mode_ids + +class WifiFeatureFlags { + public: + WifiFeatureFlags(); + virtual ~WifiFeatureFlags() = default; + + virtual std::vector<V1_0::IWifiChip::ChipMode> getChipModes(); + virtual bool isApMacRandomizationDisabled(); +}; + +} // namespace feature_flags +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_FEATURE_FLAGS_H_ diff --git a/wifi/1.0/wifi_iface_util.cpp b/wifi/1.0/wifi_iface_util.cpp new file mode 100644 index 0000000..34bc02d --- /dev/null +++ b/wifi/1.0/wifi_iface_util.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2019 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 <cstddef> +#include <iostream> +#include <limits> +#include <random> + +#include <android-base/logging.h> +#include <android-base/macros.h> +#include <private/android_filesystem_config.h> + +#undef NAN +#include "wifi_iface_util.h" + +namespace { +// Constants to set the local bit & clear the multicast bit. +constexpr uint8_t kMacAddressMulticastMask = 0x01; +constexpr uint8_t kMacAddressLocallyAssignedMask = 0x02; +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace iface_util { + +WifiIfaceUtil::WifiIfaceUtil( + const std::weak_ptr<wifi_system::InterfaceTool> iface_tool) + : iface_tool_(iface_tool), + random_mac_address_(nullptr), + event_handlers_map_() {} + +std::array<uint8_t, 6> WifiIfaceUtil::getFactoryMacAddress( + const std::string& iface_name) { + return iface_tool_.lock()->GetFactoryMacAddress(iface_name.c_str()); +} + +bool WifiIfaceUtil::setMacAddress(const std::string& iface_name, + const std::array<uint8_t, 6>& mac) { + if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) { + LOG(ERROR) << "SetUpState(false) failed."; + return false; + } + if (!iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac)) { + LOG(ERROR) << "SetMacAddress failed."; + return false; + } + if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) { + LOG(ERROR) << "SetUpState(true) failed."; + return false; + } + IfaceEventHandlers event_handlers = {}; + const auto it = event_handlers_map_.find(iface_name); + if (it != event_handlers_map_.end()) { + event_handlers = it->second; + } + if (event_handlers.on_state_toggle_off_on != nullptr) { + event_handlers.on_state_toggle_off_on(iface_name); + } + LOG(DEBUG) << "Successfully SetMacAddress."; + return true; +} + +std::array<uint8_t, 6> WifiIfaceUtil::getOrCreateRandomMacAddress() { + if (random_mac_address_) { + return *random_mac_address_.get(); + } + random_mac_address_ = + std::make_unique<std::array<uint8_t, 6>>(createRandomMacAddress()); + return *random_mac_address_.get(); +} + +void WifiIfaceUtil::registerIfaceEventHandlers(const std::string& iface_name, + IfaceEventHandlers handlers) { + event_handlers_map_[iface_name] = handlers; +} + +void WifiIfaceUtil::unregisterIfaceEventHandlers( + const std::string& iface_name) { + event_handlers_map_.erase(iface_name); +} + +std::array<uint8_t, 6> WifiIfaceUtil::createRandomMacAddress() { + std::array<uint8_t, 6> address = {}; + std::random_device rd; + std::default_random_engine engine(rd()); + std::uniform_int_distribution<uint8_t> dist( + std::numeric_limits<uint8_t>::min(), + std::numeric_limits<uint8_t>::max()); + for (size_t i = 0; i < address.size(); i++) { + address[i] = dist(engine); + } + // Set the local bit and clear the multicast bit. + address[0] |= kMacAddressLocallyAssignedMask; + address[0] &= ~kMacAddressMulticastMask; + return address; +} +} // namespace iface_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi_iface_util.h b/wifi/1.0/wifi_iface_util.h new file mode 100644 index 0000000..98073e0 --- /dev/null +++ b/wifi/1.0/wifi_iface_util.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2019 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_IFACE_UTIL_H_ +#define WIFI_IFACE_UTIL_H_ + +#include <wifi_system/interface_tool.h> + +#include <android/hardware/wifi/1.0/IWifi.h> + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace iface_util { + +// Iface event handlers. +struct IfaceEventHandlers { + // Callback to be invoked when the iface is set down & up for MAC address + // change. + std::function<void(const std::string& iface_name)> on_state_toggle_off_on; +}; + +/** + * Util class for common iface operations. + */ +class WifiIfaceUtil { + public: + WifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool); + virtual ~WifiIfaceUtil() = default; + + virtual std::array<uint8_t, 6> getFactoryMacAddress( + const std::string& iface_name); + virtual bool setMacAddress(const std::string& iface_name, + const std::array<uint8_t, 6>& mac); + // Get or create a random MAC address. The MAC address returned from + // this method will remain the same throughout the lifetime of the HAL + // daemon. (So, changes on every reboot) + virtual std::array<uint8_t, 6> getOrCreateRandomMacAddress(); + + // Register for any iface event callbacks for the provided interface. + virtual void registerIfaceEventHandlers(const std::string& iface_name, + IfaceEventHandlers handlers); + virtual void unregisterIfaceEventHandlers(const std::string& iface_name); + + private: + std::array<uint8_t, 6> createRandomMacAddress(); + + std::weak_ptr<wifi_system::InterfaceTool> iface_tool_; + std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_; + std::map<std::string, IfaceEventHandlers> event_handlers_map_; +}; + +} // namespace iface_util +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_IFACE_UTIL_H_ diff --git a/wifi/1.0/wifi_legacy_hal.cpp b/wifi/1.0/wifi_legacy_hal.cpp new file mode 100644 index 0000000..485bd16 --- /dev/null +++ b/wifi/1.0/wifi_legacy_hal.cpp @@ -0,0 +1,1455 @@ +/* + * 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 <chrono> + +#include <android-base/logging.h> +#include <cutils/properties.h> + +#include "hidl_sync_util.h" +#include "wifi_legacy_hal.h" +#include "wifi_legacy_hal_stubs.h" + +namespace { +// Constants ported over from the legacy HAL calling code +// (com_android_server_wifi_WifiNative.cpp). This will all be thrown +// away when this shim layer is replaced by the real vendor +// implementation. +static constexpr uint32_t kMaxVersionStringLength = 256; +static constexpr uint32_t kMaxCachedGscanResults = 64; +static constexpr uint32_t kMaxGscanFrequenciesForBand = 64; +static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128; +static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32; +static constexpr uint32_t kMaxRingBuffers = 10; +static constexpr uint32_t kMaxStopCompleteWaitMs = 100; +static constexpr char kDriverPropName[] = "wlan.driver.status"; + +// Helper function to create a non-const char* for legacy Hal API's. +std::vector<char> makeCharVec(const std::string& str) { + std::vector<char> vec(str.size() + 1); + vec.assign(str.begin(), str.end()); + vec.push_back('\0'); + return vec; +} +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace legacy_hal { +// 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 onAsyncStopComplete(wifi_handle handle) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_stop_complete_internal_callback) { + on_stop_complete_internal_callback(handle); + // Invalidate this callback since we don't want this firing again. + on_stop_complete_internal_callback = nullptr; + } +} + +// Callback to be invoked for driver dump. +std::function<void(char*, int)> on_driver_memory_dump_internal_callback; +void onSyncDriverMemoryDump(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<void(char*, int)> on_firmware_memory_dump_internal_callback; +void onSyncFirmwareMemoryDump(char* buffer, int buffer_size) { + if (on_firmware_memory_dump_internal_callback) { + on_firmware_memory_dump_internal_callback(buffer, buffer_size); + } +} + +// Callback to be invoked for Gscan events. +std::function<void(wifi_request_id, wifi_scan_event)> + on_gscan_event_internal_callback; +void onAsyncGscanEvent(wifi_request_id id, wifi_scan_event event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_gscan_event_internal_callback) { + on_gscan_event_internal_callback(id, event); + } +} + +// Callback to be invoked for Gscan full results. +std::function<void(wifi_request_id, wifi_scan_result*, uint32_t)> + on_gscan_full_result_internal_callback; +void onAsyncGscanFullResult(wifi_request_id id, wifi_scan_result* result, + uint32_t buckets_scanned) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_gscan_full_result_internal_callback) { + on_gscan_full_result_internal_callback(id, result, buckets_scanned); + } +} + +// Callback to be invoked for link layer stats results. +std::function<void((wifi_request_id, wifi_iface_stat*, int, wifi_radio_stat*))> + on_link_layer_stats_result_internal_callback; +void onSyncLinkLayerStatsResult(wifi_request_id id, wifi_iface_stat* iface_stat, + int num_radios, wifi_radio_stat* radio_stat) { + if (on_link_layer_stats_result_internal_callback) { + on_link_layer_stats_result_internal_callback(id, iface_stat, num_radios, + radio_stat); + } +} + +// Callback to be invoked for rssi threshold breach. +std::function<void((wifi_request_id, uint8_t*, int8_t))> + on_rssi_threshold_breached_internal_callback; +void onAsyncRssiThresholdBreached(wifi_request_id id, uint8_t* bssid, + int8_t rssi) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_rssi_threshold_breached_internal_callback) { + on_rssi_threshold_breached_internal_callback(id, bssid, rssi); + } +} + +// Callback to be invoked for ring buffer data indication. +std::function<void(char*, char*, int, wifi_ring_buffer_status*)> + on_ring_buffer_data_internal_callback; +void onAsyncRingBufferData(char* ring_name, char* buffer, int buffer_size, + wifi_ring_buffer_status* status) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_ring_buffer_data_internal_callback) { + on_ring_buffer_data_internal_callback(ring_name, buffer, buffer_size, + status); + } +} + +// Callback to be invoked for error alert indication. +std::function<void(wifi_request_id, char*, int, int)> + on_error_alert_internal_callback; +void onAsyncErrorAlert(wifi_request_id id, char* buffer, int buffer_size, + int err_code) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_error_alert_internal_callback) { + on_error_alert_internal_callback(id, buffer, buffer_size, err_code); + } +} + +// Callback to be invoked for radio mode change indication. +std::function<void(wifi_request_id, uint32_t, wifi_mac_info*)> + on_radio_mode_change_internal_callback; +void onAsyncRadioModeChange(wifi_request_id id, uint32_t num_macs, + wifi_mac_info* mac_infos) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_radio_mode_change_internal_callback) { + on_radio_mode_change_internal_callback(id, num_macs, mac_infos); + } +} + +// Callback to be invoked for rtt results results. +std::function<void(wifi_request_id, unsigned num_results, + wifi_rtt_result* rtt_results[])> + on_rtt_results_internal_callback; +void onAsyncRttResults(wifi_request_id id, unsigned num_results, + wifi_rtt_result* rtt_results[]) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_rtt_results_internal_callback) { + on_rtt_results_internal_callback(id, num_results, rtt_results); + on_rtt_results_internal_callback = nullptr; + } +} + +// Callbacks for the various NAN operations. +// NOTE: These have very little conversions to perform before invoking the user +// callbacks. +// So, handle all of them here directly to avoid adding an unnecessary layer. +std::function<void(transaction_id, const NanResponseMsg&)> + on_nan_notify_response_user_callback; +void onAysncNanNotifyResponse(transaction_id id, NanResponseMsg* msg) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_notify_response_user_callback && msg) { + on_nan_notify_response_user_callback(id, *msg); + } +} + +std::function<void(const NanPublishRepliedInd&)> + on_nan_event_publish_replied_user_callback; +void onAysncNanEventPublishReplied(NanPublishRepliedInd* /* event */) { + LOG(ERROR) << "onAysncNanEventPublishReplied triggered"; +} + +std::function<void(const NanPublishTerminatedInd&)> + on_nan_event_publish_terminated_user_callback; +void onAysncNanEventPublishTerminated(NanPublishTerminatedInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_publish_terminated_user_callback && event) { + on_nan_event_publish_terminated_user_callback(*event); + } +} + +std::function<void(const NanMatchInd&)> on_nan_event_match_user_callback; +void onAysncNanEventMatch(NanMatchInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_match_user_callback && event) { + on_nan_event_match_user_callback(*event); + } +} + +std::function<void(const NanMatchExpiredInd&)> + on_nan_event_match_expired_user_callback; +void onAysncNanEventMatchExpired(NanMatchExpiredInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_match_expired_user_callback && event) { + on_nan_event_match_expired_user_callback(*event); + } +} + +std::function<void(const NanSubscribeTerminatedInd&)> + on_nan_event_subscribe_terminated_user_callback; +void onAysncNanEventSubscribeTerminated(NanSubscribeTerminatedInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_subscribe_terminated_user_callback && event) { + on_nan_event_subscribe_terminated_user_callback(*event); + } +} + +std::function<void(const NanFollowupInd&)> on_nan_event_followup_user_callback; +void onAysncNanEventFollowup(NanFollowupInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_followup_user_callback && event) { + on_nan_event_followup_user_callback(*event); + } +} + +std::function<void(const NanDiscEngEventInd&)> + on_nan_event_disc_eng_event_user_callback; +void onAysncNanEventDiscEngEvent(NanDiscEngEventInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_disc_eng_event_user_callback && event) { + on_nan_event_disc_eng_event_user_callback(*event); + } +} + +std::function<void(const NanDisabledInd&)> on_nan_event_disabled_user_callback; +void onAysncNanEventDisabled(NanDisabledInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_disabled_user_callback && event) { + on_nan_event_disabled_user_callback(*event); + } +} + +std::function<void(const NanTCAInd&)> on_nan_event_tca_user_callback; +void onAysncNanEventTca(NanTCAInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_tca_user_callback && event) { + on_nan_event_tca_user_callback(*event); + } +} + +std::function<void(const NanBeaconSdfPayloadInd&)> + on_nan_event_beacon_sdf_payload_user_callback; +void onAysncNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_beacon_sdf_payload_user_callback && event) { + on_nan_event_beacon_sdf_payload_user_callback(*event); + } +} + +std::function<void(const NanDataPathRequestInd&)> + on_nan_event_data_path_request_user_callback; +void onAysncNanEventDataPathRequest(NanDataPathRequestInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_data_path_request_user_callback && event) { + on_nan_event_data_path_request_user_callback(*event); + } +} +std::function<void(const NanDataPathConfirmInd&)> + on_nan_event_data_path_confirm_user_callback; +void onAysncNanEventDataPathConfirm(NanDataPathConfirmInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_data_path_confirm_user_callback && event) { + on_nan_event_data_path_confirm_user_callback(*event); + } +} + +std::function<void(const NanDataPathEndInd&)> + on_nan_event_data_path_end_user_callback; +void onAysncNanEventDataPathEnd(NanDataPathEndInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_data_path_end_user_callback && event) { + on_nan_event_data_path_end_user_callback(*event); + } +} + +std::function<void(const NanTransmitFollowupInd&)> + on_nan_event_transmit_follow_up_user_callback; +void onAysncNanEventTransmitFollowUp(NanTransmitFollowupInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_transmit_follow_up_user_callback && event) { + on_nan_event_transmit_follow_up_user_callback(*event); + } +} + +std::function<void(const NanRangeRequestInd&)> + on_nan_event_range_request_user_callback; +void onAysncNanEventRangeRequest(NanRangeRequestInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_range_request_user_callback && event) { + on_nan_event_range_request_user_callback(*event); + } +} + +std::function<void(const NanRangeReportInd&)> + on_nan_event_range_report_user_callback; +void onAysncNanEventRangeReport(NanRangeReportInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_range_report_user_callback && event) { + on_nan_event_range_report_user_callback(*event); + } +} + +std::function<void(const NanDataPathScheduleUpdateInd&)> + on_nan_event_schedule_update_user_callback; +void onAsyncNanEventScheduleUpdate(NanDataPathScheduleUpdateInd* event) { + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (on_nan_event_schedule_update_user_callback && event) { + on_nan_event_schedule_update_user_callback(*event); + } +} +// End of the free-standing "C" style callbacks. + +WifiLegacyHal::WifiLegacyHal( + const std::weak_ptr<wifi_system::InterfaceTool> iface_tool) + : global_handle_(nullptr), + awaiting_event_loop_termination_(false), + is_started_(false), + iface_tool_(iface_tool) {} + +wifi_error WifiLegacyHal::initialize() { + LOG(DEBUG) << "Initialize legacy HAL"; + // TODO: Add back the HAL Tool if we need to. All we need from the HAL tool + // for now is this function call which we can directly call. + if (!initHalFuncTableWithStubs(&global_func_table_)) { + LOG(ERROR) + << "Failed to initialize legacy hal function table with stubs"; + return WIFI_ERROR_UNKNOWN; + } + wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_); + if (status != WIFI_SUCCESS) { + LOG(ERROR) << "Failed to initialize legacy hal function table"; + } + return status; +} + +wifi_error WifiLegacyHal::start() { + // Ensure that we're starting in a good state. + CHECK(global_func_table_.wifi_initialize && !global_handle_ && + iface_name_to_handle_.empty() && !awaiting_event_loop_termination_); + if (is_started_) { + LOG(DEBUG) << "Legacy HAL already started"; + return WIFI_SUCCESS; + } + LOG(DEBUG) << "Waiting for the driver ready"; + wifi_error status = global_func_table_.wifi_wait_for_driver_ready(); + if (status == WIFI_ERROR_TIMED_OUT) { + LOG(ERROR) << "Timed out awaiting driver ready"; + return status; + } + property_set(kDriverPropName, "ok"); + + LOG(DEBUG) << "Starting legacy HAL"; + if (!iface_tool_.lock()->SetWifiUpState(true)) { + LOG(ERROR) << "Failed to set WiFi interface up"; + return WIFI_ERROR_UNKNOWN; + } + status = global_func_table_.wifi_initialize(&global_handle_); + if (status != WIFI_SUCCESS || !global_handle_) { + LOG(ERROR) << "Failed to retrieve global handle"; + return status; + } + std::thread(&WifiLegacyHal::runEventLoop, this).detach(); + status = retrieveIfaceHandles(); + if (status != WIFI_SUCCESS || iface_name_to_handle_.empty()) { + LOG(ERROR) << "Failed to retrieve wlan interface handle"; + return status; + } + LOG(DEBUG) << "Legacy HAL start complete"; + is_started_ = true; + return WIFI_SUCCESS; +} + +wifi_error WifiLegacyHal::stop( + /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, + const std::function<void()>& on_stop_complete_user_callback) { + if (!is_started_) { + LOG(DEBUG) << "Legacy HAL already stopped"; + on_stop_complete_user_callback(); + return WIFI_SUCCESS; + } + LOG(DEBUG) << "Stopping legacy HAL"; + on_stop_complete_internal_callback = [on_stop_complete_user_callback, + this](wifi_handle handle) { + CHECK_EQ(global_handle_, handle) << "Handle mismatch"; + LOG(INFO) << "Legacy HAL stop complete callback received"; + // Invalidate all the internal pointers now that the HAL is + // stopped. + invalidate(); + iface_tool_.lock()->SetWifiUpState(false); + on_stop_complete_user_callback(); + is_started_ = false; + }; + awaiting_event_loop_termination_ = true; + global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete); + const auto status = stop_wait_cv_.wait_for( + *lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs), + [this] { return !awaiting_event_loop_termination_; }); + if (!status) { + LOG(ERROR) << "Legacy HAL stop failed or timed out"; + return WIFI_ERROR_UNKNOWN; + } + LOG(DEBUG) << "Legacy HAL stop complete"; + return WIFI_SUCCESS; +} + +bool WifiLegacyHal::isStarted() { return is_started_; } + +std::pair<wifi_error, std::string> WifiLegacyHal::getDriverVersion( + const std::string& iface_name) { + std::array<char, kMaxVersionStringLength> buffer; + buffer.fill(0); + wifi_error status = global_func_table_.wifi_get_driver_version( + getIfaceHandle(iface_name), buffer.data(), buffer.size()); + return {status, buffer.data()}; +} + +std::pair<wifi_error, std::string> WifiLegacyHal::getFirmwareVersion( + const std::string& iface_name) { + std::array<char, kMaxVersionStringLength> buffer; + buffer.fill(0); + wifi_error status = global_func_table_.wifi_get_firmware_version( + getIfaceHandle(iface_name), buffer.data(), buffer.size()); + return {status, buffer.data()}; +} + +std::pair<wifi_error, std::vector<uint8_t>> +WifiLegacyHal::requestDriverMemoryDump(const std::string& iface_name) { + std::vector<uint8_t> driver_dump; + on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer, + int buffer_size) { + driver_dump.insert(driver_dump.end(), + reinterpret_cast<uint8_t*>(buffer), + reinterpret_cast<uint8_t*>(buffer) + buffer_size); + }; + wifi_error status = global_func_table_.wifi_get_driver_memory_dump( + getIfaceHandle(iface_name), {onSyncDriverMemoryDump}); + on_driver_memory_dump_internal_callback = nullptr; + return {status, std::move(driver_dump)}; +} + +std::pair<wifi_error, std::vector<uint8_t>> +WifiLegacyHal::requestFirmwareMemoryDump(const std::string& iface_name) { + std::vector<uint8_t> firmware_dump; + on_firmware_memory_dump_internal_callback = + [&firmware_dump](char* buffer, int buffer_size) { + firmware_dump.insert( + firmware_dump.end(), reinterpret_cast<uint8_t*>(buffer), + reinterpret_cast<uint8_t*>(buffer) + buffer_size); + }; + wifi_error status = global_func_table_.wifi_get_firmware_memory_dump( + getIfaceHandle(iface_name), {onSyncFirmwareMemoryDump}); + on_firmware_memory_dump_internal_callback = nullptr; + return {status, std::move(firmware_dump)}; +} + +std::pair<wifi_error, uint32_t> WifiLegacyHal::getSupportedFeatureSet( + const std::string& iface_name) { + feature_set set; + static_assert(sizeof(set) == sizeof(uint32_t), + "Some feature_flags can not be represented in output"); + wifi_error status = global_func_table_.wifi_get_supported_feature_set( + getIfaceHandle(iface_name), &set); + return {status, static_cast<uint32_t>(set)}; +} + +std::pair<wifi_error, PacketFilterCapabilities> +WifiLegacyHal::getPacketFilterCapabilities(const std::string& iface_name) { + PacketFilterCapabilities caps; + wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities( + getIfaceHandle(iface_name), &caps.version, &caps.max_len); + return {status, caps}; +} + +wifi_error WifiLegacyHal::setPacketFilter(const std::string& iface_name, + const std::vector<uint8_t>& program) { + return global_func_table_.wifi_set_packet_filter( + getIfaceHandle(iface_name), program.data(), program.size()); +} + +std::pair<wifi_error, std::vector<uint8_t>> +WifiLegacyHal::readApfPacketFilterData(const std::string& iface_name) { + PacketFilterCapabilities caps; + wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities( + getIfaceHandle(iface_name), &caps.version, &caps.max_len); + if (status != WIFI_SUCCESS) { + return {status, {}}; + } + + // Size the buffer to read the entire program & work memory. + std::vector<uint8_t> buffer(caps.max_len); + + status = global_func_table_.wifi_read_packet_filter( + getIfaceHandle(iface_name), /*src_offset=*/0, buffer.data(), + buffer.size()); + return {status, move(buffer)}; +} + +std::pair<wifi_error, wifi_gscan_capabilities> +WifiLegacyHal::getGscanCapabilities(const std::string& iface_name) { + wifi_gscan_capabilities caps; + wifi_error status = global_func_table_.wifi_get_gscan_capabilities( + getIfaceHandle(iface_name), &caps); + return {status, caps}; +} + +wifi_error WifiLegacyHal::startGscan( + const std::string& iface_name, wifi_request_id id, + const wifi_scan_cmd_params& params, + const std::function<void(wifi_request_id)>& on_failure_user_callback, + const on_gscan_results_callback& on_results_user_callback, + const on_gscan_full_result_callback& on_full_result_user_callback) { + // If there is already an ongoing background scan, reject new scan requests. + if (on_gscan_event_internal_callback || + on_gscan_full_result_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + + // This callback will be used to either trigger |on_results_user_callback| + // or |on_failure_user_callback|. + on_gscan_event_internal_callback = + [iface_name, on_failure_user_callback, on_results_user_callback, this]( + wifi_request_id id, wifi_scan_event event) { + switch (event) { + case WIFI_SCAN_RESULTS_AVAILABLE: + case WIFI_SCAN_THRESHOLD_NUM_SCANS: + case WIFI_SCAN_THRESHOLD_PERCENT: { + wifi_error status; + std::vector<wifi_cached_scan_results> cached_scan_results; + std::tie(status, cached_scan_results) = + getGscanCachedResults(iface_name); + if (status == WIFI_SUCCESS) { + on_results_user_callback(id, cached_scan_results); + return; + } + FALLTHROUGH_INTENDED; + } + // Fall through if failed. Failure to retrieve cached scan + // results should trigger a background scan failure. + case WIFI_SCAN_FAILED: + on_failure_user_callback(id); + on_gscan_event_internal_callback = nullptr; + on_gscan_full_result_internal_callback = nullptr; + return; + } + LOG(FATAL) << "Unexpected gscan event received: " << event; + }; + + on_gscan_full_result_internal_callback = [on_full_result_user_callback]( + wifi_request_id id, + wifi_scan_result* result, + uint32_t buckets_scanned) { + if (result) { + on_full_result_user_callback(id, result, buckets_scanned); + } + }; + + wifi_scan_result_handler handler = {onAsyncGscanFullResult, + onAsyncGscanEvent}; + wifi_error status = global_func_table_.wifi_start_gscan( + id, getIfaceHandle(iface_name), params, handler); + if (status != WIFI_SUCCESS) { + on_gscan_event_internal_callback = nullptr; + on_gscan_full_result_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::stopGscan(const std::string& iface_name, + wifi_request_id id) { + // If there is no an ongoing background scan, reject stop requests. + // TODO(b/32337212): This needs to be handled by the HIDL object because we + // need to return the NOT_STARTED error code. + if (!on_gscan_event_internal_callback && + !on_gscan_full_result_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + wifi_error status = + global_func_table_.wifi_stop_gscan(id, getIfaceHandle(iface_name)); + // If the request Id is wrong, don't stop the ongoing background scan. Any + // other error should be treated as the end of background scan. + if (status != WIFI_ERROR_INVALID_REQUEST_ID) { + on_gscan_event_internal_callback = nullptr; + on_gscan_full_result_internal_callback = nullptr; + } + return status; +} + +std::pair<wifi_error, std::vector<uint32_t>> +WifiLegacyHal::getValidFrequenciesForBand(const std::string& iface_name, + wifi_band band) { + static_assert(sizeof(uint32_t) >= sizeof(wifi_channel), + "Wifi Channel cannot be represented in output"); + std::vector<uint32_t> freqs; + freqs.resize(kMaxGscanFrequenciesForBand); + int32_t num_freqs = 0; + wifi_error status = global_func_table_.wifi_get_valid_channels( + getIfaceHandle(iface_name), band, freqs.size(), + reinterpret_cast<wifi_channel*>(freqs.data()), &num_freqs); + CHECK(num_freqs >= 0 && + static_cast<uint32_t>(num_freqs) <= kMaxGscanFrequenciesForBand); + freqs.resize(num_freqs); + return {status, std::move(freqs)}; +} + +wifi_error WifiLegacyHal::setDfsFlag(const std::string& iface_name, + bool dfs_on) { + return global_func_table_.wifi_set_nodfs_flag(getIfaceHandle(iface_name), + dfs_on ? 0 : 1); +} + +wifi_error WifiLegacyHal::enableLinkLayerStats(const std::string& iface_name, + bool debug) { + wifi_link_layer_params params; + params.mpdu_size_threshold = kLinkLayerStatsDataMpduSizeThreshold; + params.aggressive_statistics_gathering = debug; + return global_func_table_.wifi_set_link_stats(getIfaceHandle(iface_name), + params); +} + +wifi_error WifiLegacyHal::disableLinkLayerStats(const std::string& iface_name) { + // TODO: Do we care about these responses? + uint32_t clear_mask_rsp; + uint8_t stop_rsp; + return global_func_table_.wifi_clear_link_stats( + getIfaceHandle(iface_name), 0xFFFFFFFF, &clear_mask_rsp, 1, &stop_rsp); +} + +std::pair<wifi_error, LinkLayerStats> WifiLegacyHal::getLinkLayerStats( + const std::string& iface_name) { + LinkLayerStats link_stats{}; + LinkLayerStats* link_stats_ptr = &link_stats; + + on_link_layer_stats_result_internal_callback = + [&link_stats_ptr](wifi_request_id /* id */, + wifi_iface_stat* iface_stats_ptr, int num_radios, + wifi_radio_stat* radio_stats_ptr) { + wifi_radio_stat* l_radio_stats_ptr; + + if (iface_stats_ptr != nullptr) { + link_stats_ptr->iface = *iface_stats_ptr; + link_stats_ptr->iface.num_peers = 0; + } else { + LOG(ERROR) << "Invalid iface stats in link layer stats"; + } + if (num_radios <= 0 || radio_stats_ptr == nullptr) { + LOG(ERROR) << "Invalid radio stats in link layer stats"; + return; + } + l_radio_stats_ptr = radio_stats_ptr; + for (int i = 0; i < num_radios; i++) { + LinkLayerRadioStats radio; + + radio.stats = *l_radio_stats_ptr; + // Copy over the tx level array to the separate vector. + if (l_radio_stats_ptr->num_tx_levels > 0 && + l_radio_stats_ptr->tx_time_per_levels != nullptr) { + radio.tx_time_per_levels.assign( + l_radio_stats_ptr->tx_time_per_levels, + l_radio_stats_ptr->tx_time_per_levels + + l_radio_stats_ptr->num_tx_levels); + } + radio.stats.num_tx_levels = 0; + radio.stats.tx_time_per_levels = nullptr; + /* Copy over the channel stat to separate vector */ + if (l_radio_stats_ptr->num_channels > 0) { + /* Copy the channel stats */ + radio.channel_stats.assign( + l_radio_stats_ptr->channels, + l_radio_stats_ptr->channels + + l_radio_stats_ptr->num_channels); + } + link_stats_ptr->radios.push_back(radio); + l_radio_stats_ptr = + (wifi_radio_stat*)((u8*)l_radio_stats_ptr + + sizeof(wifi_radio_stat) + + (sizeof(wifi_channel_stat) * + l_radio_stats_ptr->num_channels)); + } + }; + + wifi_error status = global_func_table_.wifi_get_link_stats( + 0, getIfaceHandle(iface_name), {onSyncLinkLayerStatsResult}); + on_link_layer_stats_result_internal_callback = nullptr; + return {status, link_stats}; +} + +wifi_error WifiLegacyHal::startRssiMonitoring( + const std::string& iface_name, wifi_request_id id, int8_t max_rssi, + int8_t min_rssi, + const on_rssi_threshold_breached_callback& + on_threshold_breached_user_callback) { + if (on_rssi_threshold_breached_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_rssi_threshold_breached_internal_callback = + [on_threshold_breached_user_callback](wifi_request_id id, + uint8_t* bssid_ptr, int8_t rssi) { + if (!bssid_ptr) { + return; + } + std::array<uint8_t, 6> bssid_arr; + // |bssid_ptr| pointer is assumed to have 6 bytes for the mac + // address. + std::copy(bssid_ptr, bssid_ptr + 6, std::begin(bssid_arr)); + on_threshold_breached_user_callback(id, bssid_arr, rssi); + }; + wifi_error status = global_func_table_.wifi_start_rssi_monitoring( + id, getIfaceHandle(iface_name), max_rssi, min_rssi, + {onAsyncRssiThresholdBreached}); + if (status != WIFI_SUCCESS) { + on_rssi_threshold_breached_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::stopRssiMonitoring(const std::string& iface_name, + wifi_request_id id) { + if (!on_rssi_threshold_breached_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + wifi_error status = global_func_table_.wifi_stop_rssi_monitoring( + id, getIfaceHandle(iface_name)); + // If the request Id is wrong, don't stop the ongoing rssi monitoring. Any + // other error should be treated as the end of background scan. + if (status != WIFI_ERROR_INVALID_REQUEST_ID) { + on_rssi_threshold_breached_internal_callback = nullptr; + } + return status; +} + +std::pair<wifi_error, wifi_roaming_capabilities> +WifiLegacyHal::getRoamingCapabilities(const std::string& iface_name) { + wifi_roaming_capabilities caps; + wifi_error status = global_func_table_.wifi_get_roaming_capabilities( + getIfaceHandle(iface_name), &caps); + return {status, caps}; +} + +wifi_error WifiLegacyHal::configureRoaming(const std::string& iface_name, + const wifi_roaming_config& config) { + wifi_roaming_config config_internal = config; + return global_func_table_.wifi_configure_roaming(getIfaceHandle(iface_name), + &config_internal); +} + +wifi_error WifiLegacyHal::enableFirmwareRoaming(const std::string& iface_name, + fw_roaming_state_t state) { + return global_func_table_.wifi_enable_firmware_roaming( + getIfaceHandle(iface_name), state); +} + +wifi_error WifiLegacyHal::configureNdOffload(const std::string& iface_name, + bool enable) { + return global_func_table_.wifi_configure_nd_offload( + getIfaceHandle(iface_name), enable); +} + +wifi_error WifiLegacyHal::startSendingOffloadedPacket( + const std::string& iface_name, uint32_t cmd_id, uint16_t ether_type, + const std::vector<uint8_t>& ip_packet_data, + const std::array<uint8_t, 6>& src_address, + const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms) { + std::vector<uint8_t> ip_packet_data_internal(ip_packet_data); + std::vector<uint8_t> src_address_internal( + src_address.data(), src_address.data() + src_address.size()); + std::vector<uint8_t> dst_address_internal( + dst_address.data(), dst_address.data() + dst_address.size()); + return global_func_table_.wifi_start_sending_offloaded_packet( + cmd_id, getIfaceHandle(iface_name), ether_type, + ip_packet_data_internal.data(), ip_packet_data_internal.size(), + src_address_internal.data(), dst_address_internal.data(), period_in_ms); +} + +wifi_error WifiLegacyHal::stopSendingOffloadedPacket( + const std::string& iface_name, uint32_t cmd_id) { + return global_func_table_.wifi_stop_sending_offloaded_packet( + cmd_id, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::setScanningMacOui(const std::string& iface_name, + const std::array<uint8_t, 3>& oui) { + std::vector<uint8_t> oui_internal(oui.data(), oui.data() + oui.size()); + return global_func_table_.wifi_set_scanning_mac_oui( + getIfaceHandle(iface_name), oui_internal.data()); +} + +wifi_error WifiLegacyHal::selectTxPowerScenario(const std::string& iface_name, + wifi_power_scenario scenario) { + return global_func_table_.wifi_select_tx_power_scenario( + getIfaceHandle(iface_name), scenario); +} + +wifi_error WifiLegacyHal::resetTxPowerScenario(const std::string& iface_name) { + return global_func_table_.wifi_reset_tx_power_scenario( + getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::setLatencyMode(const std::string& iface_name, + wifi_latency_mode mode) { + return global_func_table_.wifi_set_latency_mode(getIfaceHandle(iface_name), + mode); +} + +std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet( + const std::string& iface_name) { + uint32_t supported_feature_flags; + wifi_error status = + global_func_table_.wifi_get_logger_supported_feature_set( + getIfaceHandle(iface_name), &supported_feature_flags); + return {status, supported_feature_flags}; +} + +wifi_error WifiLegacyHal::startPktFateMonitoring( + const std::string& iface_name) { + return global_func_table_.wifi_start_pkt_fate_monitoring( + getIfaceHandle(iface_name)); +} + +std::pair<wifi_error, std::vector<wifi_tx_report>> WifiLegacyHal::getTxPktFates( + const std::string& iface_name) { + std::vector<wifi_tx_report> tx_pkt_fates; + tx_pkt_fates.resize(MAX_FATE_LOG_LEN); + size_t num_fates = 0; + wifi_error status = global_func_table_.wifi_get_tx_pkt_fates( + getIfaceHandle(iface_name), tx_pkt_fates.data(), tx_pkt_fates.size(), + &num_fates); + CHECK(num_fates <= MAX_FATE_LOG_LEN); + tx_pkt_fates.resize(num_fates); + return {status, std::move(tx_pkt_fates)}; +} + +std::pair<wifi_error, std::vector<wifi_rx_report>> WifiLegacyHal::getRxPktFates( + const std::string& iface_name) { + std::vector<wifi_rx_report> rx_pkt_fates; + rx_pkt_fates.resize(MAX_FATE_LOG_LEN); + size_t num_fates = 0; + wifi_error status = global_func_table_.wifi_get_rx_pkt_fates( + getIfaceHandle(iface_name), rx_pkt_fates.data(), rx_pkt_fates.size(), + &num_fates); + CHECK(num_fates <= MAX_FATE_LOG_LEN); + rx_pkt_fates.resize(num_fates); + return {status, std::move(rx_pkt_fates)}; +} + +std::pair<wifi_error, WakeReasonStats> WifiLegacyHal::getWakeReasonStats( + const std::string& iface_name) { + WakeReasonStats stats; + stats.cmd_event_wake_cnt.resize(kMaxWakeReasonStatsArraySize); + stats.driver_fw_local_wake_cnt.resize(kMaxWakeReasonStatsArraySize); + + // This legacy struct needs separate memory to store the variable sized wake + // reason types. + stats.wake_reason_cnt.cmd_event_wake_cnt = + reinterpret_cast<int32_t*>(stats.cmd_event_wake_cnt.data()); + stats.wake_reason_cnt.cmd_event_wake_cnt_sz = + stats.cmd_event_wake_cnt.size(); + stats.wake_reason_cnt.cmd_event_wake_cnt_used = 0; + stats.wake_reason_cnt.driver_fw_local_wake_cnt = + reinterpret_cast<int32_t*>(stats.driver_fw_local_wake_cnt.data()); + stats.wake_reason_cnt.driver_fw_local_wake_cnt_sz = + stats.driver_fw_local_wake_cnt.size(); + stats.wake_reason_cnt.driver_fw_local_wake_cnt_used = 0; + + wifi_error status = global_func_table_.wifi_get_wake_reason_stats( + getIfaceHandle(iface_name), &stats.wake_reason_cnt); + + CHECK( + stats.wake_reason_cnt.cmd_event_wake_cnt_used >= 0 && + static_cast<uint32_t>(stats.wake_reason_cnt.cmd_event_wake_cnt_used) <= + kMaxWakeReasonStatsArraySize); + stats.cmd_event_wake_cnt.resize( + stats.wake_reason_cnt.cmd_event_wake_cnt_used); + stats.wake_reason_cnt.cmd_event_wake_cnt = nullptr; + + CHECK(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used >= 0 && + static_cast<uint32_t>( + stats.wake_reason_cnt.driver_fw_local_wake_cnt_used) <= + kMaxWakeReasonStatsArraySize); + stats.driver_fw_local_wake_cnt.resize( + stats.wake_reason_cnt.driver_fw_local_wake_cnt_used); + stats.wake_reason_cnt.driver_fw_local_wake_cnt = nullptr; + + return {status, stats}; +} + +wifi_error WifiLegacyHal::registerRingBufferCallbackHandler( + const std::string& iface_name, + const on_ring_buffer_data_callback& on_user_data_callback) { + if (on_ring_buffer_data_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_ring_buffer_data_internal_callback = + [on_user_data_callback](char* ring_name, char* buffer, int buffer_size, + wifi_ring_buffer_status* status) { + if (status && buffer) { + std::vector<uint8_t> buffer_vector( + reinterpret_cast<uint8_t*>(buffer), + reinterpret_cast<uint8_t*>(buffer) + buffer_size); + on_user_data_callback(ring_name, buffer_vector, *status); + } + }; + wifi_error status = global_func_table_.wifi_set_log_handler( + 0, getIfaceHandle(iface_name), {onAsyncRingBufferData}); + if (status != WIFI_SUCCESS) { + on_ring_buffer_data_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::deregisterRingBufferCallbackHandler( + const std::string& iface_name) { + if (!on_ring_buffer_data_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_ring_buffer_data_internal_callback = nullptr; + return global_func_table_.wifi_reset_log_handler( + 0, getIfaceHandle(iface_name)); +} + +std::pair<wifi_error, std::vector<wifi_ring_buffer_status>> +WifiLegacyHal::getRingBuffersStatus(const std::string& iface_name) { + std::vector<wifi_ring_buffer_status> ring_buffers_status; + ring_buffers_status.resize(kMaxRingBuffers); + uint32_t num_rings = kMaxRingBuffers; + wifi_error status = global_func_table_.wifi_get_ring_buffers_status( + getIfaceHandle(iface_name), &num_rings, ring_buffers_status.data()); + CHECK(num_rings <= kMaxRingBuffers); + ring_buffers_status.resize(num_rings); + return {status, std::move(ring_buffers_status)}; +} + +wifi_error WifiLegacyHal::startRingBufferLogging(const std::string& iface_name, + const std::string& ring_name, + uint32_t verbose_level, + uint32_t max_interval_sec, + uint32_t min_data_size) { + return global_func_table_.wifi_start_logging( + getIfaceHandle(iface_name), verbose_level, 0, max_interval_sec, + min_data_size, makeCharVec(ring_name).data()); +} + +wifi_error WifiLegacyHal::getRingBufferData(const std::string& iface_name, + const std::string& ring_name) { + return global_func_table_.wifi_get_ring_data(getIfaceHandle(iface_name), + makeCharVec(ring_name).data()); +} + +wifi_error WifiLegacyHal::registerErrorAlertCallbackHandler( + const std::string& iface_name, + const on_error_alert_callback& on_user_alert_callback) { + if (on_error_alert_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_error_alert_internal_callback = [on_user_alert_callback]( + wifi_request_id id, char* buffer, + int buffer_size, int err_code) { + if (buffer) { + CHECK(id == 0); + on_user_alert_callback( + err_code, + std::vector<uint8_t>( + reinterpret_cast<uint8_t*>(buffer), + reinterpret_cast<uint8_t*>(buffer) + buffer_size)); + } + }; + wifi_error status = global_func_table_.wifi_set_alert_handler( + 0, getIfaceHandle(iface_name), {onAsyncErrorAlert}); + if (status != WIFI_SUCCESS) { + on_error_alert_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::deregisterErrorAlertCallbackHandler( + const std::string& iface_name) { + if (!on_error_alert_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_error_alert_internal_callback = nullptr; + return global_func_table_.wifi_reset_alert_handler( + 0, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::registerRadioModeChangeCallbackHandler( + const std::string& iface_name, + const on_radio_mode_change_callback& on_user_change_callback) { + if (on_radio_mode_change_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + on_radio_mode_change_internal_callback = [on_user_change_callback]( + wifi_request_id /* id */, + uint32_t num_macs, + wifi_mac_info* mac_infos_arr) { + if (num_macs > 0 && mac_infos_arr) { + std::vector<WifiMacInfo> mac_infos_vec; + for (uint32_t i = 0; i < num_macs; i++) { + WifiMacInfo mac_info; + mac_info.wlan_mac_id = mac_infos_arr[i].wlan_mac_id; + mac_info.mac_band = mac_infos_arr[i].mac_band; + for (int32_t j = 0; j < mac_infos_arr[i].num_iface; j++) { + WifiIfaceInfo iface_info; + iface_info.name = mac_infos_arr[i].iface_info[j].iface_name; + iface_info.channel = mac_infos_arr[i].iface_info[j].channel; + mac_info.iface_infos.push_back(iface_info); + } + mac_infos_vec.push_back(mac_info); + } + on_user_change_callback(mac_infos_vec); + } + }; + wifi_error status = global_func_table_.wifi_set_radio_mode_change_handler( + 0, getIfaceHandle(iface_name), {onAsyncRadioModeChange}); + if (status != WIFI_SUCCESS) { + on_radio_mode_change_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::startRttRangeRequest( + const std::string& iface_name, wifi_request_id id, + const std::vector<wifi_rtt_config>& rtt_configs, + const on_rtt_results_callback& on_results_user_callback) { + if (on_rtt_results_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + + on_rtt_results_internal_callback = + [on_results_user_callback](wifi_request_id id, unsigned num_results, + wifi_rtt_result* rtt_results[]) { + if (num_results > 0 && !rtt_results) { + LOG(ERROR) << "Unexpected nullptr in RTT results"; + return; + } + std::vector<const wifi_rtt_result*> rtt_results_vec; + std::copy_if(rtt_results, rtt_results + num_results, + back_inserter(rtt_results_vec), + [](wifi_rtt_result* rtt_result) { + return rtt_result != nullptr; + }); + on_results_user_callback(id, rtt_results_vec); + }; + + std::vector<wifi_rtt_config> rtt_configs_internal(rtt_configs); + wifi_error status = global_func_table_.wifi_rtt_range_request( + id, getIfaceHandle(iface_name), rtt_configs.size(), + rtt_configs_internal.data(), {onAsyncRttResults}); + if (status != WIFI_SUCCESS) { + on_rtt_results_internal_callback = nullptr; + } + return status; +} + +wifi_error WifiLegacyHal::cancelRttRangeRequest( + const std::string& iface_name, wifi_request_id id, + const std::vector<std::array<uint8_t, 6>>& mac_addrs) { + if (!on_rtt_results_internal_callback) { + return WIFI_ERROR_NOT_AVAILABLE; + } + static_assert(sizeof(mac_addr) == sizeof(std::array<uint8_t, 6>), + "MAC address size mismatch"); + // TODO: How do we handle partial cancels (i.e only a subset of enabled mac + // addressed are cancelled). + std::vector<std::array<uint8_t, 6>> mac_addrs_internal(mac_addrs); + wifi_error status = global_func_table_.wifi_rtt_range_cancel( + id, getIfaceHandle(iface_name), mac_addrs.size(), + reinterpret_cast<mac_addr*>(mac_addrs_internal.data())); + // If the request Id is wrong, don't stop the ongoing range request. Any + // other error should be treated as the end of rtt ranging. + if (status != WIFI_ERROR_INVALID_REQUEST_ID) { + on_rtt_results_internal_callback = nullptr; + } + return status; +} + +std::pair<wifi_error, wifi_rtt_capabilities> WifiLegacyHal::getRttCapabilities( + const std::string& iface_name) { + wifi_rtt_capabilities rtt_caps; + wifi_error status = global_func_table_.wifi_get_rtt_capabilities( + getIfaceHandle(iface_name), &rtt_caps); + return {status, rtt_caps}; +} + +std::pair<wifi_error, wifi_rtt_responder> WifiLegacyHal::getRttResponderInfo( + const std::string& iface_name) { + wifi_rtt_responder rtt_responder; + wifi_error status = global_func_table_.wifi_rtt_get_responder_info( + getIfaceHandle(iface_name), &rtt_responder); + return {status, rtt_responder}; +} + +wifi_error WifiLegacyHal::enableRttResponder( + const std::string& iface_name, wifi_request_id id, + const wifi_channel_info& channel_hint, uint32_t max_duration_secs, + const wifi_rtt_responder& info) { + wifi_rtt_responder info_internal(info); + return global_func_table_.wifi_enable_responder( + id, getIfaceHandle(iface_name), channel_hint, max_duration_secs, + &info_internal); +} + +wifi_error WifiLegacyHal::disableRttResponder(const std::string& iface_name, + wifi_request_id id) { + return global_func_table_.wifi_disable_responder( + id, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::setRttLci(const std::string& iface_name, + wifi_request_id id, + const wifi_lci_information& info) { + wifi_lci_information info_internal(info); + return global_func_table_.wifi_set_lci(id, getIfaceHandle(iface_name), + &info_internal); +} + +wifi_error WifiLegacyHal::setRttLcr(const std::string& iface_name, + wifi_request_id id, + const wifi_lcr_information& info) { + wifi_lcr_information info_internal(info); + return global_func_table_.wifi_set_lcr(id, getIfaceHandle(iface_name), + &info_internal); +} + +wifi_error WifiLegacyHal::nanRegisterCallbackHandlers( + const std::string& iface_name, const NanCallbackHandlers& user_callbacks) { + on_nan_notify_response_user_callback = user_callbacks.on_notify_response; + on_nan_event_publish_terminated_user_callback = + user_callbacks.on_event_publish_terminated; + on_nan_event_match_user_callback = user_callbacks.on_event_match; + on_nan_event_match_expired_user_callback = + user_callbacks.on_event_match_expired; + on_nan_event_subscribe_terminated_user_callback = + user_callbacks.on_event_subscribe_terminated; + on_nan_event_followup_user_callback = user_callbacks.on_event_followup; + on_nan_event_disc_eng_event_user_callback = + user_callbacks.on_event_disc_eng_event; + on_nan_event_disabled_user_callback = user_callbacks.on_event_disabled; + on_nan_event_tca_user_callback = user_callbacks.on_event_tca; + on_nan_event_beacon_sdf_payload_user_callback = + user_callbacks.on_event_beacon_sdf_payload; + on_nan_event_data_path_request_user_callback = + user_callbacks.on_event_data_path_request; + on_nan_event_data_path_confirm_user_callback = + user_callbacks.on_event_data_path_confirm; + on_nan_event_data_path_end_user_callback = + user_callbacks.on_event_data_path_end; + on_nan_event_transmit_follow_up_user_callback = + user_callbacks.on_event_transmit_follow_up; + on_nan_event_range_request_user_callback = + user_callbacks.on_event_range_request; + on_nan_event_range_report_user_callback = + user_callbacks.on_event_range_report; + on_nan_event_schedule_update_user_callback = + user_callbacks.on_event_schedule_update; + + return global_func_table_.wifi_nan_register_handler( + getIfaceHandle(iface_name), + {onAysncNanNotifyResponse, onAysncNanEventPublishReplied, + onAysncNanEventPublishTerminated, onAysncNanEventMatch, + onAysncNanEventMatchExpired, onAysncNanEventSubscribeTerminated, + onAysncNanEventFollowup, onAysncNanEventDiscEngEvent, + onAysncNanEventDisabled, onAysncNanEventTca, + onAysncNanEventBeaconSdfPayload, onAysncNanEventDataPathRequest, + onAysncNanEventDataPathConfirm, onAysncNanEventDataPathEnd, + onAysncNanEventTransmitFollowUp, onAysncNanEventRangeRequest, + onAysncNanEventRangeReport, onAsyncNanEventScheduleUpdate}); +} + +wifi_error WifiLegacyHal::nanEnableRequest(const std::string& iface_name, + transaction_id id, + const NanEnableRequest& msg) { + NanEnableRequest msg_internal(msg); + return global_func_table_.wifi_nan_enable_request( + id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanDisableRequest(const std::string& iface_name, + transaction_id id) { + return global_func_table_.wifi_nan_disable_request( + id, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::nanPublishRequest(const std::string& iface_name, + transaction_id id, + const NanPublishRequest& msg) { + NanPublishRequest msg_internal(msg); + return global_func_table_.wifi_nan_publish_request( + id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanPublishCancelRequest( + const std::string& iface_name, transaction_id id, + const NanPublishCancelRequest& msg) { + NanPublishCancelRequest msg_internal(msg); + return global_func_table_.wifi_nan_publish_cancel_request( + id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanSubscribeRequest(const std::string& iface_name, + transaction_id id, + const NanSubscribeRequest& msg) { + NanSubscribeRequest msg_internal(msg); + return global_func_table_.wifi_nan_subscribe_request( + id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanSubscribeCancelRequest( + const std::string& iface_name, transaction_id id, + const NanSubscribeCancelRequest& msg) { + NanSubscribeCancelRequest msg_internal(msg); + return global_func_table_.wifi_nan_subscribe_cancel_request( + id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanTransmitFollowupRequest( + const std::string& iface_name, transaction_id id, + const NanTransmitFollowupRequest& msg) { + NanTransmitFollowupRequest msg_internal(msg); + return global_func_table_.wifi_nan_transmit_followup_request( + id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanStatsRequest(const std::string& iface_name, + transaction_id id, + const NanStatsRequest& msg) { + NanStatsRequest msg_internal(msg); + return global_func_table_.wifi_nan_stats_request( + id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanConfigRequest(const std::string& iface_name, + transaction_id id, + const NanConfigRequest& msg) { + NanConfigRequest msg_internal(msg); + return global_func_table_.wifi_nan_config_request( + id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanTcaRequest(const std::string& iface_name, + transaction_id id, + const NanTCARequest& msg) { + NanTCARequest msg_internal(msg); + return global_func_table_.wifi_nan_tca_request( + id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanBeaconSdfPayloadRequest( + const std::string& iface_name, transaction_id id, + const NanBeaconSdfPayloadRequest& msg) { + NanBeaconSdfPayloadRequest msg_internal(msg); + return global_func_table_.wifi_nan_beacon_sdf_payload_request( + id, getIfaceHandle(iface_name), &msg_internal); +} + +std::pair<wifi_error, NanVersion> WifiLegacyHal::nanGetVersion() { + NanVersion version; + wifi_error status = + global_func_table_.wifi_nan_get_version(global_handle_, &version); + return {status, version}; +} + +wifi_error WifiLegacyHal::nanGetCapabilities(const std::string& iface_name, + transaction_id id) { + return global_func_table_.wifi_nan_get_capabilities( + id, getIfaceHandle(iface_name)); +} + +wifi_error WifiLegacyHal::nanDataInterfaceCreate( + const std::string& iface_name, transaction_id id, + const std::string& data_iface_name) { + return global_func_table_.wifi_nan_data_interface_create( + id, getIfaceHandle(iface_name), makeCharVec(data_iface_name).data()); +} + +wifi_error WifiLegacyHal::nanDataInterfaceDelete( + const std::string& iface_name, transaction_id id, + const std::string& data_iface_name) { + return global_func_table_.wifi_nan_data_interface_delete( + id, getIfaceHandle(iface_name), makeCharVec(data_iface_name).data()); +} + +wifi_error WifiLegacyHal::nanDataRequestInitiator( + const std::string& iface_name, transaction_id id, + const NanDataPathInitiatorRequest& msg) { + NanDataPathInitiatorRequest msg_internal(msg); + return global_func_table_.wifi_nan_data_request_initiator( + id, getIfaceHandle(iface_name), &msg_internal); +} + +wifi_error WifiLegacyHal::nanDataIndicationResponse( + const std::string& iface_name, transaction_id id, + const NanDataPathIndicationResponse& msg) { + NanDataPathIndicationResponse msg_internal(msg); + return global_func_table_.wifi_nan_data_indication_response( + id, getIfaceHandle(iface_name), &msg_internal); +} + +typedef struct { + u8 num_ndp_instances; + NanDataPathId ndp_instance_id; +} NanDataPathEndSingleNdpIdRequest; + +wifi_error WifiLegacyHal::nanDataEnd(const std::string& iface_name, + transaction_id id, + uint32_t ndpInstanceId) { + NanDataPathEndSingleNdpIdRequest msg; + msg.num_ndp_instances = 1; + msg.ndp_instance_id = ndpInstanceId; + wifi_error status = global_func_table_.wifi_nan_data_end( + id, getIfaceHandle(iface_name), (NanDataPathEndRequest*)&msg); + return status; +} + +wifi_error WifiLegacyHal::setCountryCode(const std::string& iface_name, + std::array<int8_t, 2> code) { + std::string code_str(code.data(), code.data() + code.size()); + return global_func_table_.wifi_set_country_code(getIfaceHandle(iface_name), + code_str.c_str()); +} + +wifi_error WifiLegacyHal::retrieveIfaceHandles() { + 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"; + return status; + } + for (int i = 0; i < num_iface_handles; ++i) { + std::array<char, IFNAMSIZ> iface_name_arr = {}; + status = global_func_table_.wifi_get_iface_name( + iface_handles[i], iface_name_arr.data(), iface_name_arr.size()); + if (status != WIFI_SUCCESS) { + LOG(WARNING) << "Failed to get interface handle name"; + continue; + } + // Assuming the interface name is null terminated since the legacy HAL + // API does not return a size. + std::string iface_name(iface_name_arr.data()); + LOG(INFO) << "Adding interface handle for " << iface_name; + iface_name_to_handle_[iface_name] = iface_handles[i]; + } + return WIFI_SUCCESS; +} + +wifi_interface_handle WifiLegacyHal::getIfaceHandle( + const std::string& iface_name) { + const auto iface_handle_iter = iface_name_to_handle_.find(iface_name); + if (iface_handle_iter == iface_name_to_handle_.end()) { + LOG(ERROR) << "Unknown iface name: " << iface_name; + return nullptr; + } + return iface_handle_iter->second; +} + +void WifiLegacyHal::runEventLoop() { + LOG(DEBUG) << "Starting legacy HAL event loop"; + global_func_table_.wifi_event_loop(global_handle_); + const auto lock = hidl_sync_util::acquireGlobalLock(); + if (!awaiting_event_loop_termination_) { + LOG(FATAL) + << "Legacy HAL event loop terminated, but HAL was not stopping"; + } + LOG(DEBUG) << "Legacy HAL event loop terminated"; + awaiting_event_loop_termination_ = false; + stop_wait_cv_.notify_one(); +} + +std::pair<wifi_error, std::vector<wifi_cached_scan_results>> +WifiLegacyHal::getGscanCachedResults(const std::string& iface_name) { + std::vector<wifi_cached_scan_results> cached_scan_results; + cached_scan_results.resize(kMaxCachedGscanResults); + int32_t num_results = 0; + wifi_error status = global_func_table_.wifi_get_cached_gscan_results( + getIfaceHandle(iface_name), true /* always flush */, + cached_scan_results.size(), cached_scan_results.data(), &num_results); + CHECK(num_results >= 0 && + static_cast<uint32_t>(num_results) <= kMaxCachedGscanResults); + cached_scan_results.resize(num_results); + // Check for invalid IE lengths in these cached scan results and correct it. + for (auto& cached_scan_result : cached_scan_results) { + int num_scan_results = cached_scan_result.num_results; + for (int i = 0; i < num_scan_results; i++) { + auto& scan_result = cached_scan_result.results[i]; + if (scan_result.ie_length > 0) { + LOG(DEBUG) << "Cached scan result has non-zero IE length " + << scan_result.ie_length; + scan_result.ie_length = 0; + } + } + } + return {status, std::move(cached_scan_results)}; +} + +void WifiLegacyHal::invalidate() { + global_handle_ = nullptr; + iface_name_to_handle_.clear(); + on_driver_memory_dump_internal_callback = nullptr; + on_firmware_memory_dump_internal_callback = nullptr; + on_gscan_event_internal_callback = nullptr; + on_gscan_full_result_internal_callback = nullptr; + on_link_layer_stats_result_internal_callback = nullptr; + on_rssi_threshold_breached_internal_callback = nullptr; + on_ring_buffer_data_internal_callback = nullptr; + on_error_alert_internal_callback = nullptr; + on_radio_mode_change_internal_callback = nullptr; + on_rtt_results_internal_callback = nullptr; + on_nan_notify_response_user_callback = nullptr; + on_nan_event_publish_terminated_user_callback = nullptr; + on_nan_event_match_user_callback = nullptr; + on_nan_event_match_expired_user_callback = nullptr; + on_nan_event_subscribe_terminated_user_callback = nullptr; + on_nan_event_followup_user_callback = nullptr; + on_nan_event_disc_eng_event_user_callback = nullptr; + on_nan_event_disabled_user_callback = nullptr; + on_nan_event_tca_user_callback = nullptr; + on_nan_event_beacon_sdf_payload_user_callback = nullptr; + on_nan_event_data_path_request_user_callback = nullptr; + on_nan_event_data_path_confirm_user_callback = nullptr; + on_nan_event_data_path_end_user_callback = nullptr; + on_nan_event_transmit_follow_up_user_callback = nullptr; + on_nan_event_range_request_user_callback = nullptr; + on_nan_event_range_report_user_callback = nullptr; + on_nan_event_schedule_update_user_callback = nullptr; +} + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi_legacy_hal.h b/wifi/1.0/wifi_legacy_hal.h new file mode 100644 index 0000000..9cfa172 --- /dev/null +++ b/wifi/1.0/wifi_legacy_hal.h @@ -0,0 +1,404 @@ +/* + * 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_HAL_H_ +#define WIFI_LEGACY_HAL_H_ + +#include <condition_variable> +#include <functional> +#include <map> +#include <thread> +#include <vector> + +#include <wifi_system/interface_tool.h> + +// HACK: The include inside the namespace below also transitively includes a +// bunch of libc headers into the namespace, which leads to functions like +// socketpair being defined in +// android::hardware::wifi::V1_1::implementation::legacy_hal. Include this one +// particular header as a hacky workaround until that's fixed. +#include <sys/socket.h> + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +// This is in a separate namespace to prevent typename conflicts between +// the legacy HAL types and the HIDL interface types. +namespace legacy_hal { +// Wrap all the types defined inside the legacy HAL header files inside this +// namespace. +#include <hardware_legacy/wifi_hal.h> + +// APF capabilities supported by the iface. +struct PacketFilterCapabilities { + uint32_t version; + uint32_t max_len; +}; + +// WARNING: We don't care about the variable sized members of either +// |wifi_iface_stat|, |wifi_radio_stat| structures. So, using the pragma +// to escape the compiler warnings regarding this. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wgnu-variable-sized-type-not-at-end" +// The |wifi_radio_stat.tx_time_per_levels| stats is provided as a pointer in +// |wifi_radio_stat| structure in the legacy HAL API. Separate that out +// into a separate return element to avoid passing pointers around. +struct LinkLayerRadioStats { + wifi_radio_stat stats; + std::vector<uint32_t> tx_time_per_levels; + std::vector<wifi_channel_stat> channel_stats; +}; + +struct LinkLayerStats { + wifi_iface_stat iface; + std::vector<LinkLayerRadioStats> radios; +}; +#pragma GCC diagnostic pop + +// The |WLAN_DRIVER_WAKE_REASON_CNT.cmd_event_wake_cnt| and +// |WLAN_DRIVER_WAKE_REASON_CNT.driver_fw_local_wake_cnt| stats is provided +// as a pointer in |WLAN_DRIVER_WAKE_REASON_CNT| structure in the legacy HAL +// API. Separate that out into a separate return elements to avoid passing +// pointers around. +struct WakeReasonStats { + WLAN_DRIVER_WAKE_REASON_CNT wake_reason_cnt; + std::vector<uint32_t> cmd_event_wake_cnt; + std::vector<uint32_t> driver_fw_local_wake_cnt; +}; + +// NAN response and event callbacks struct. +struct NanCallbackHandlers { + // NotifyResponse invoked to notify the status of the Request. + std::function<void(transaction_id, const NanResponseMsg&)> + on_notify_response; + // Various event callbacks. + std::function<void(const NanPublishTerminatedInd&)> + on_event_publish_terminated; + std::function<void(const NanMatchInd&)> on_event_match; + std::function<void(const NanMatchExpiredInd&)> on_event_match_expired; + std::function<void(const NanSubscribeTerminatedInd&)> + on_event_subscribe_terminated; + std::function<void(const NanFollowupInd&)> on_event_followup; + std::function<void(const NanDiscEngEventInd&)> on_event_disc_eng_event; + std::function<void(const NanDisabledInd&)> on_event_disabled; + std::function<void(const NanTCAInd&)> on_event_tca; + std::function<void(const NanBeaconSdfPayloadInd&)> + on_event_beacon_sdf_payload; + std::function<void(const NanDataPathRequestInd&)> + on_event_data_path_request; + std::function<void(const NanDataPathConfirmInd&)> + on_event_data_path_confirm; + std::function<void(const NanDataPathEndInd&)> on_event_data_path_end; + std::function<void(const NanTransmitFollowupInd&)> + on_event_transmit_follow_up; + std::function<void(const NanRangeRequestInd&)> on_event_range_request; + std::function<void(const NanRangeReportInd&)> on_event_range_report; + std::function<void(const NanDataPathScheduleUpdateInd&)> + on_event_schedule_update; +}; + +// Full scan results contain IE info and are hence passed by reference, to +// preserve the variable length array member |ie_data|. Callee must not retain +// the pointer. +using on_gscan_full_result_callback = + std::function<void(wifi_request_id, const wifi_scan_result*, uint32_t)>; +// These scan results don't contain any IE info, so no need to pass by +// reference. +using on_gscan_results_callback = std::function<void( + wifi_request_id, const std::vector<wifi_cached_scan_results>&)>; + +// Invoked when the rssi value breaches the thresholds set. +using on_rssi_threshold_breached_callback = + std::function<void(wifi_request_id, std::array<uint8_t, 6>, int8_t)>; + +// Callback for RTT range request results. +// Rtt results contain IE info and are hence passed by reference, to +// preserve the |LCI| and |LCR| pointers. Callee must not retain +// the pointer. +using on_rtt_results_callback = std::function<void( + wifi_request_id, const std::vector<const wifi_rtt_result*>&)>; + +// Callback for ring buffer data. +using on_ring_buffer_data_callback = + std::function<void(const std::string&, const std::vector<uint8_t>&, + const wifi_ring_buffer_status&)>; + +// Callback for alerts. +using on_error_alert_callback = + std::function<void(int32_t, const std::vector<uint8_t>&)>; + +// Struct for the mac info from the legacy HAL. This is a cleaner version +// of the |wifi_mac_info| & |wifi_iface_info|. +typedef struct { + std::string name; + wifi_channel channel; +} WifiIfaceInfo; + +typedef struct { + uint32_t wlan_mac_id; + /* BIT MASK of BIT(WLAN_MAC*) as represented by wlan_mac_band */ + uint32_t mac_band; + /* Represents the connected Wi-Fi interfaces associated with each MAC */ + std::vector<WifiIfaceInfo> iface_infos; +} WifiMacInfo; + +// Callback for radio mode change +using on_radio_mode_change_callback = + std::function<void(const std::vector<WifiMacInfo>&)>; + +/** + * Class that encapsulates all legacy HAL interactions. + * This class manages the lifetime of the event loop thread used by legacy HAL. + * + * Note: There will only be a single instance of this class created in the Wifi + * object and will be valid for the lifetime of the process. + */ +class WifiLegacyHal { + public: + WifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool); + virtual ~WifiLegacyHal() = default; + + // Initialize the legacy HAL function table. + virtual wifi_error initialize(); + // Start the legacy HAL and the event looper thread. + virtual wifi_error start(); + // Deinitialize the legacy HAL and wait for the event loop thread to exit + // using a predefined timeout. + virtual wifi_error stop(std::unique_lock<std::recursive_mutex>* lock, + const std::function<void()>& on_complete_callback); + // Checks if legacy HAL has successfully started + bool isStarted(); + // Wrappers for all the functions in the legacy HAL function table. + virtual std::pair<wifi_error, std::string> getDriverVersion( + const std::string& iface_name); + virtual std::pair<wifi_error, std::string> getFirmwareVersion( + const std::string& iface_name); + std::pair<wifi_error, std::vector<uint8_t>> requestDriverMemoryDump( + const std::string& iface_name); + std::pair<wifi_error, std::vector<uint8_t>> requestFirmwareMemoryDump( + const std::string& iface_name); + std::pair<wifi_error, uint32_t> getSupportedFeatureSet( + const std::string& iface_name); + // APF functions. + std::pair<wifi_error, PacketFilterCapabilities> getPacketFilterCapabilities( + const std::string& iface_name); + wifi_error setPacketFilter(const std::string& iface_name, + const std::vector<uint8_t>& program); + std::pair<wifi_error, std::vector<uint8_t>> readApfPacketFilterData( + const std::string& iface_name); + // Gscan functions. + std::pair<wifi_error, wifi_gscan_capabilities> getGscanCapabilities( + const std::string& iface_name); + // These API's provides a simplified interface over the legacy Gscan API's: + // a) All scan events from the legacy HAL API other than the + // |WIFI_SCAN_FAILED| are treated as notification of results. + // This method then retrieves the cached scan results from the legacy + // HAL API and triggers the externally provided + // |on_results_user_callback| on success. + // b) |WIFI_SCAN_FAILED| scan event or failure to retrieve cached scan + // results + // triggers the externally provided |on_failure_user_callback|. + // c) Full scan result event triggers the externally provided + // |on_full_result_user_callback|. + wifi_error startGscan( + const std::string& iface_name, wifi_request_id id, + const wifi_scan_cmd_params& params, + const std::function<void(wifi_request_id)>& on_failure_callback, + const on_gscan_results_callback& on_results_callback, + const on_gscan_full_result_callback& on_full_result_callback); + wifi_error stopGscan(const std::string& iface_name, wifi_request_id id); + std::pair<wifi_error, std::vector<uint32_t>> getValidFrequenciesForBand( + const std::string& iface_name, wifi_band band); + virtual wifi_error setDfsFlag(const std::string& iface_name, bool dfs_on); + // Link layer stats functions. + wifi_error enableLinkLayerStats(const std::string& iface_name, bool debug); + wifi_error disableLinkLayerStats(const std::string& iface_name); + std::pair<wifi_error, LinkLayerStats> getLinkLayerStats( + const std::string& iface_name); + // RSSI monitor functions. + wifi_error startRssiMonitoring(const std::string& iface_name, + wifi_request_id id, int8_t max_rssi, + int8_t min_rssi, + const on_rssi_threshold_breached_callback& + on_threshold_breached_callback); + wifi_error stopRssiMonitoring(const std::string& iface_name, + wifi_request_id id); + std::pair<wifi_error, wifi_roaming_capabilities> getRoamingCapabilities( + const std::string& iface_name); + wifi_error configureRoaming(const std::string& iface_name, + const wifi_roaming_config& config); + wifi_error enableFirmwareRoaming(const std::string& iface_name, + fw_roaming_state_t state); + wifi_error configureNdOffload(const std::string& iface_name, bool enable); + wifi_error startSendingOffloadedPacket( + const std::string& iface_name, uint32_t cmd_id, uint16_t ether_type, + const std::vector<uint8_t>& ip_packet_data, + const std::array<uint8_t, 6>& src_address, + const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms); + wifi_error stopSendingOffloadedPacket(const std::string& iface_name, + uint32_t cmd_id); + wifi_error setScanningMacOui(const std::string& iface_name, + const std::array<uint8_t, 3>& oui); + virtual wifi_error selectTxPowerScenario(const std::string& iface_name, + wifi_power_scenario scenario); + virtual wifi_error resetTxPowerScenario(const std::string& iface_name); + wifi_error setLatencyMode(const std::string& iface_name, + wifi_latency_mode mode); + // Logger/debug functions. + std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet( + const std::string& iface_name); + wifi_error startPktFateMonitoring(const std::string& iface_name); + std::pair<wifi_error, std::vector<wifi_tx_report>> getTxPktFates( + const std::string& iface_name); + std::pair<wifi_error, std::vector<wifi_rx_report>> getRxPktFates( + const std::string& iface_name); + std::pair<wifi_error, WakeReasonStats> getWakeReasonStats( + const std::string& iface_name); + wifi_error registerRingBufferCallbackHandler( + const std::string& iface_name, + const on_ring_buffer_data_callback& on_data_callback); + wifi_error deregisterRingBufferCallbackHandler( + const std::string& iface_name); + std::pair<wifi_error, std::vector<wifi_ring_buffer_status>> + getRingBuffersStatus(const std::string& iface_name); + wifi_error startRingBufferLogging(const std::string& iface_name, + const std::string& ring_name, + uint32_t verbose_level, + uint32_t max_interval_sec, + uint32_t min_data_size); + wifi_error getRingBufferData(const std::string& iface_name, + const std::string& ring_name); + wifi_error registerErrorAlertCallbackHandler( + const std::string& iface_name, + const on_error_alert_callback& on_alert_callback); + wifi_error deregisterErrorAlertCallbackHandler( + const std::string& iface_name); + // Radio mode functions. + virtual wifi_error registerRadioModeChangeCallbackHandler( + const std::string& iface_name, + const on_radio_mode_change_callback& on_user_change_callback); + // RTT functions. + wifi_error startRttRangeRequest( + const std::string& iface_name, wifi_request_id id, + const std::vector<wifi_rtt_config>& rtt_configs, + const on_rtt_results_callback& on_results_callback); + wifi_error cancelRttRangeRequest( + const std::string& iface_name, wifi_request_id id, + const std::vector<std::array<uint8_t, 6>>& mac_addrs); + std::pair<wifi_error, wifi_rtt_capabilities> getRttCapabilities( + const std::string& iface_name); + std::pair<wifi_error, wifi_rtt_responder> getRttResponderInfo( + const std::string& iface_name); + wifi_error enableRttResponder(const std::string& iface_name, + wifi_request_id id, + const wifi_channel_info& channel_hint, + uint32_t max_duration_secs, + const wifi_rtt_responder& info); + wifi_error disableRttResponder(const std::string& iface_name, + wifi_request_id id); + wifi_error setRttLci(const std::string& iface_name, wifi_request_id id, + const wifi_lci_information& info); + wifi_error setRttLcr(const std::string& iface_name, wifi_request_id id, + const wifi_lcr_information& info); + // NAN functions. + virtual wifi_error nanRegisterCallbackHandlers( + const std::string& iface_name, const NanCallbackHandlers& callbacks); + wifi_error nanEnableRequest(const std::string& iface_name, + transaction_id id, const NanEnableRequest& msg); + virtual wifi_error nanDisableRequest(const std::string& iface_name, + transaction_id id); + wifi_error nanPublishRequest(const std::string& iface_name, + transaction_id id, + const NanPublishRequest& msg); + wifi_error nanPublishCancelRequest(const std::string& iface_name, + transaction_id id, + const NanPublishCancelRequest& msg); + wifi_error nanSubscribeRequest(const std::string& iface_name, + transaction_id id, + const NanSubscribeRequest& msg); + wifi_error nanSubscribeCancelRequest(const std::string& iface_name, + transaction_id id, + const NanSubscribeCancelRequest& msg); + wifi_error nanTransmitFollowupRequest( + const std::string& iface_name, transaction_id id, + const NanTransmitFollowupRequest& msg); + wifi_error nanStatsRequest(const std::string& iface_name, transaction_id id, + const NanStatsRequest& msg); + wifi_error nanConfigRequest(const std::string& iface_name, + transaction_id id, const NanConfigRequest& msg); + wifi_error nanTcaRequest(const std::string& iface_name, transaction_id id, + const NanTCARequest& msg); + wifi_error nanBeaconSdfPayloadRequest( + const std::string& iface_name, transaction_id id, + const NanBeaconSdfPayloadRequest& msg); + std::pair<wifi_error, NanVersion> nanGetVersion(); + wifi_error nanGetCapabilities(const std::string& iface_name, + transaction_id id); + wifi_error nanDataInterfaceCreate(const std::string& iface_name, + transaction_id id, + const std::string& data_iface_name); + virtual wifi_error nanDataInterfaceDelete( + const std::string& iface_name, transaction_id id, + const std::string& data_iface_name); + wifi_error nanDataRequestInitiator(const std::string& iface_name, + transaction_id id, + const NanDataPathInitiatorRequest& msg); + wifi_error nanDataIndicationResponse( + const std::string& iface_name, transaction_id id, + const NanDataPathIndicationResponse& msg); + wifi_error nanDataEnd(const std::string& iface_name, transaction_id id, + uint32_t ndpInstanceId); + // AP functions. + wifi_error setCountryCode(const std::string& iface_name, + std::array<int8_t, 2> code); + + private: + // Retrieve interface handles for all the available interfaces. + wifi_error retrieveIfaceHandles(); + wifi_interface_handle getIfaceHandle(const std::string& iface_name); + // Run the legacy HAL event loop thread. + void runEventLoop(); + // Retrieve the cached gscan results to pass the results back to the + // external callbacks. + std::pair<wifi_error, std::vector<wifi_cached_scan_results>> + getGscanCachedResults(const std::string& iface_name); + void invalidate(); + + // 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_; + // Map of interface name to handle that is to be used for all interface + // specific operations. + std::map<std::string, wifi_interface_handle> iface_name_to_handle_; + // Flag to indicate if we have initiated the cleanup of legacy HAL. + std::atomic<bool> awaiting_event_loop_termination_; + std::condition_variable_any stop_wait_cv_; + // Flag to indicate if the legacy HAL has been started. + bool is_started_; + std::weak_ptr<wifi_system::InterfaceTool> iface_tool_; +}; + +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_LEGACY_HAL_H_ diff --git a/wifi/1.0/wifi_legacy_hal_stubs.cpp b/wifi/1.0/wifi_legacy_hal_stubs.cpp new file mode 100644 index 0000000..dedd2d4 --- /dev/null +++ b/wifi/1.0/wifi_legacy_hal_stubs.cpp @@ -0,0 +1,148 @@ +/* + * 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_legacy_hal_stubs.h" + +// TODO: Remove these stubs from HalTool in libwifi-system. +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace legacy_hal { +template <typename> +struct stubFunction; + +template <typename R, typename... Args> +struct stubFunction<R (*)(Args...)> { + static constexpr R invoke(Args...) { return WIFI_ERROR_NOT_SUPPORTED; } +}; +template <typename... Args> +struct stubFunction<void (*)(Args...)> { + static constexpr void invoke(Args...) {} +}; + +template <typename T> +void populateStubFor(T* val) { + *val = &stubFunction<T>::invoke; +} + +bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) { + if (hal_fn == nullptr) { + return false; + } + populateStubFor(&hal_fn->wifi_initialize); + populateStubFor(&hal_fn->wifi_wait_for_driver_ready); + populateStubFor(&hal_fn->wifi_cleanup); + populateStubFor(&hal_fn->wifi_event_loop); + populateStubFor(&hal_fn->wifi_get_error_info); + populateStubFor(&hal_fn->wifi_get_supported_feature_set); + populateStubFor(&hal_fn->wifi_get_concurrency_matrix); + populateStubFor(&hal_fn->wifi_set_scanning_mac_oui); + populateStubFor(&hal_fn->wifi_get_supported_channels); + populateStubFor(&hal_fn->wifi_is_epr_supported); + populateStubFor(&hal_fn->wifi_get_ifaces); + populateStubFor(&hal_fn->wifi_get_iface_name); + populateStubFor(&hal_fn->wifi_set_iface_event_handler); + populateStubFor(&hal_fn->wifi_reset_iface_event_handler); + populateStubFor(&hal_fn->wifi_start_gscan); + populateStubFor(&hal_fn->wifi_stop_gscan); + populateStubFor(&hal_fn->wifi_get_cached_gscan_results); + populateStubFor(&hal_fn->wifi_set_bssid_hotlist); + populateStubFor(&hal_fn->wifi_reset_bssid_hotlist); + populateStubFor(&hal_fn->wifi_set_significant_change_handler); + populateStubFor(&hal_fn->wifi_reset_significant_change_handler); + populateStubFor(&hal_fn->wifi_get_gscan_capabilities); + populateStubFor(&hal_fn->wifi_set_link_stats); + populateStubFor(&hal_fn->wifi_get_link_stats); + populateStubFor(&hal_fn->wifi_clear_link_stats); + populateStubFor(&hal_fn->wifi_get_valid_channels); + populateStubFor(&hal_fn->wifi_rtt_range_request); + populateStubFor(&hal_fn->wifi_rtt_range_cancel); + populateStubFor(&hal_fn->wifi_get_rtt_capabilities); + populateStubFor(&hal_fn->wifi_rtt_get_responder_info); + populateStubFor(&hal_fn->wifi_enable_responder); + populateStubFor(&hal_fn->wifi_disable_responder); + populateStubFor(&hal_fn->wifi_set_nodfs_flag); + populateStubFor(&hal_fn->wifi_start_logging); + populateStubFor(&hal_fn->wifi_set_epno_list); + populateStubFor(&hal_fn->wifi_reset_epno_list); + populateStubFor(&hal_fn->wifi_set_country_code); + populateStubFor(&hal_fn->wifi_get_firmware_memory_dump); + populateStubFor(&hal_fn->wifi_set_log_handler); + populateStubFor(&hal_fn->wifi_reset_log_handler); + populateStubFor(&hal_fn->wifi_set_alert_handler); + populateStubFor(&hal_fn->wifi_reset_alert_handler); + populateStubFor(&hal_fn->wifi_get_firmware_version); + populateStubFor(&hal_fn->wifi_get_ring_buffers_status); + populateStubFor(&hal_fn->wifi_get_logger_supported_feature_set); + populateStubFor(&hal_fn->wifi_get_ring_data); + populateStubFor(&hal_fn->wifi_enable_tdls); + populateStubFor(&hal_fn->wifi_disable_tdls); + populateStubFor(&hal_fn->wifi_get_tdls_status); + populateStubFor(&hal_fn->wifi_get_tdls_capabilities); + populateStubFor(&hal_fn->wifi_get_driver_version); + populateStubFor(&hal_fn->wifi_set_passpoint_list); + populateStubFor(&hal_fn->wifi_reset_passpoint_list); + populateStubFor(&hal_fn->wifi_set_lci); + populateStubFor(&hal_fn->wifi_set_lcr); + populateStubFor(&hal_fn->wifi_start_sending_offloaded_packet); + populateStubFor(&hal_fn->wifi_stop_sending_offloaded_packet); + populateStubFor(&hal_fn->wifi_start_rssi_monitoring); + populateStubFor(&hal_fn->wifi_stop_rssi_monitoring); + populateStubFor(&hal_fn->wifi_get_wake_reason_stats); + populateStubFor(&hal_fn->wifi_configure_nd_offload); + populateStubFor(&hal_fn->wifi_get_driver_memory_dump); + populateStubFor(&hal_fn->wifi_start_pkt_fate_monitoring); + populateStubFor(&hal_fn->wifi_get_tx_pkt_fates); + populateStubFor(&hal_fn->wifi_get_rx_pkt_fates); + populateStubFor(&hal_fn->wifi_nan_enable_request); + populateStubFor(&hal_fn->wifi_nan_disable_request); + populateStubFor(&hal_fn->wifi_nan_publish_request); + populateStubFor(&hal_fn->wifi_nan_publish_cancel_request); + populateStubFor(&hal_fn->wifi_nan_subscribe_request); + populateStubFor(&hal_fn->wifi_nan_subscribe_cancel_request); + populateStubFor(&hal_fn->wifi_nan_transmit_followup_request); + populateStubFor(&hal_fn->wifi_nan_stats_request); + populateStubFor(&hal_fn->wifi_nan_config_request); + populateStubFor(&hal_fn->wifi_nan_tca_request); + populateStubFor(&hal_fn->wifi_nan_beacon_sdf_payload_request); + populateStubFor(&hal_fn->wifi_nan_register_handler); + populateStubFor(&hal_fn->wifi_nan_get_version); + populateStubFor(&hal_fn->wifi_nan_get_capabilities); + populateStubFor(&hal_fn->wifi_nan_data_interface_create); + populateStubFor(&hal_fn->wifi_nan_data_interface_delete); + populateStubFor(&hal_fn->wifi_nan_data_request_initiator); + populateStubFor(&hal_fn->wifi_nan_data_indication_response); + populateStubFor(&hal_fn->wifi_nan_data_end); + populateStubFor(&hal_fn->wifi_get_packet_filter_capabilities); + populateStubFor(&hal_fn->wifi_set_packet_filter); + populateStubFor(&hal_fn->wifi_read_packet_filter); + populateStubFor(&hal_fn->wifi_get_roaming_capabilities); + populateStubFor(&hal_fn->wifi_enable_firmware_roaming); + populateStubFor(&hal_fn->wifi_configure_roaming); + populateStubFor(&hal_fn->wifi_select_tx_power_scenario); + populateStubFor(&hal_fn->wifi_reset_tx_power_scenario); + populateStubFor(&hal_fn->wifi_set_radio_mode_change_handler); + populateStubFor(&hal_fn->wifi_set_latency_mode); + return true; +} +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi_legacy_hal_stubs.h b/wifi/1.0/wifi_legacy_hal_stubs.h new file mode 100644 index 0000000..64854e0 --- /dev/null +++ b/wifi/1.0/wifi_legacy_hal_stubs.h @@ -0,0 +1,36 @@ +/* + * 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_HAL_STUBS_H_ +#define WIFI_LEGACY_HAL_STUBS_H_ + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace legacy_hal { +#include <hardware_legacy/wifi_hal.h> + +bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn); +} // namespace legacy_hal +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_LEGACY_HAL_STUBS_H_ diff --git a/wifi/1.0/wifi_mode_controller.cpp b/wifi/1.0/wifi_mode_controller.cpp new file mode 100644 index 0000000..c392486 --- /dev/null +++ b/wifi/1.0/wifi_mode_controller.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/logging.h> +#include <android-base/macros.h> +#include <private/android_filesystem_config.h> + +#include "wifi_mode_controller.h" + +using android::hardware::wifi::V1_0::IfaceType; +using android::wifi_hal::DriverTool; + +namespace { +int convertIfaceTypeToFirmwareMode(IfaceType type) { + int mode; + switch (type) { + case IfaceType::AP: + mode = DriverTool::kFirmwareModeAp; + break; + case IfaceType::P2P: + mode = DriverTool::kFirmwareModeP2p; + break; + case IfaceType::NAN: + // NAN is exposed in STA mode currently. + mode = DriverTool::kFirmwareModeSta; + break; + case IfaceType::STA: + mode = DriverTool::kFirmwareModeSta; + break; + } + return mode; +} +} // namespace + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace mode_controller { + +WifiModeController::WifiModeController() : driver_tool_(new DriverTool) {} + +bool WifiModeController::isFirmwareModeChangeNeeded(IfaceType type) { + return driver_tool_->IsFirmwareModeChangeNeeded( + convertIfaceTypeToFirmwareMode(type)); +} + +bool WifiModeController::initialize() { + if (!driver_tool_->LoadDriver()) { + LOG(ERROR) << "Failed to load WiFi driver"; + return false; + } + return true; +} + +bool WifiModeController::changeFirmwareMode(IfaceType type) { + if (!driver_tool_->ChangeFirmwareMode( + convertIfaceTypeToFirmwareMode(type))) { + LOG(ERROR) << "Failed to change firmware mode"; + return false; + } + return true; +} + +bool WifiModeController::deinitialize() { + if (!driver_tool_->UnloadDriver()) { + LOG(ERROR) << "Failed to unload WiFi driver"; + return false; + } + return true; +} +} // namespace mode_controller +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi_mode_controller.h b/wifi/1.0/wifi_mode_controller.h new file mode 100644 index 0000000..ace5a52 --- /dev/null +++ b/wifi/1.0/wifi_mode_controller.h @@ -0,0 +1,63 @@ +/* + * 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_MODE_CONTROLLER_H_ +#define WIFI_MODE_CONTROLLER_H_ + +#include <wifi_hal/driver_tool.h> + +#include <android/hardware/wifi/1.0/IWifi.h> + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +namespace mode_controller { +using namespace android::hardware::wifi::V1_0; + +/** + * Class that encapsulates all firmware mode configuration. + * This class will perform the necessary firmware reloads to put the chip in the + * required state (essentially a wrapper over DriverTool). + */ +class WifiModeController { + public: + WifiModeController(); + virtual ~WifiModeController() = default; + + // Checks if a firmware mode change is necessary to support the specified + // iface type operations. + virtual bool isFirmwareModeChangeNeeded(IfaceType type); + virtual bool initialize(); + // Change the firmware mode to support the specified iface type operations. + virtual bool changeFirmwareMode(IfaceType type); + // Unload the driver. This should be invoked whenever |IWifi.stop()| is + // invoked. + virtual bool deinitialize(); + + private: + std::unique_ptr<wifi_hal::DriverTool> driver_tool_; +}; + +} // namespace mode_controller +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_MODE_CONTROLLER_H_ diff --git a/wifi/1.0/wifi_nan_iface.cpp b/wifi/1.0/wifi_nan_iface.cpp new file mode 100644 index 0000000..ff9f422 --- /dev/null +++ b/wifi/1.0/wifi_nan_iface.cpp @@ -0,0 +1,887 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/logging.h> + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_nan_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiNanIface::WifiNanIface( + const std::string& ifname, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util) + : ifname_(ifname), + legacy_hal_(legacy_hal), + iface_util_(iface_util), + is_valid_(true) { + // Register all the callbacks here. these should be valid for the lifetime + // of the object. Whenever the mode changes legacy HAL will remove + // all of these callbacks. + legacy_hal::NanCallbackHandlers callback_handlers; + android::wp<WifiNanIface> weak_ptr_this(this); + + // Callback for response. + callback_handlers + .on_notify_response = [weak_ptr_this]( + legacy_hal::transaction_id id, + const legacy_hal::NanResponseMsg& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus wifiNanStatus; + if (!hidl_struct_util::convertLegacyNanResponseHeaderToHidl( + msg, &wifiNanStatus)) { + LOG(ERROR) << "Failed to convert nan response header"; + return; + } + + switch (msg.response_type) { + case legacy_hal::NAN_RESPONSE_ENABLED: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyEnableResponse(id, wifiNanStatus) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_DISABLED: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyDisableResponse(id, wifiNanStatus) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_PUBLISH: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback + ->notifyStartPublishResponse( + id, wifiNanStatus, + msg.body.publish_response.publish_id) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_PUBLISH_CANCEL: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyStopPublishResponse(id, wifiNanStatus) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_TRANSMIT_FOLLOWUP: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback + ->notifyTransmitFollowupResponse(id, wifiNanStatus) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_SUBSCRIBE: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback + ->notifyStartSubscribeResponse( + id, wifiNanStatus, + msg.body.subscribe_response.subscribe_id) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_SUBSCRIBE_CANCEL: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback + ->notifyStopSubscribeResponse(id, wifiNanStatus) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_CONFIG: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback->notifyConfigResponse(id, wifiNanStatus) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_GET_CAPABILITIES: { + NanCapabilities hidl_struct; + if (!hidl_struct_util:: + convertLegacyNanCapabilitiesResponseToHidl( + msg.body.nan_capabilities, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback + ->notifyCapabilitiesResponse(id, wifiNanStatus, + hidl_struct) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_INTERFACE_CREATE: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback + ->notifyCreateDataInterfaceResponse(id, + wifiNanStatus) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_INTERFACE_DELETE: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback + ->notifyDeleteDataInterfaceResponse(id, + wifiNanStatus) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_INITIATOR_RESPONSE: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback + ->notifyInitiateDataPathResponse( + id, wifiNanStatus, + msg.body.data_request_response.ndp_instance_id) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_RESPONDER_RESPONSE: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback + ->notifyRespondToDataPathIndicationResponse( + id, wifiNanStatus) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_DP_END: { + for (const auto& callback : + shared_ptr_this->getEventCallbacks()) { + if (!callback + ->notifyTerminateDataPathResponse(id, + wifiNanStatus) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + break; + } + case legacy_hal::NAN_RESPONSE_BEACON_SDF_PAYLOAD: + /* fall through */ + case legacy_hal::NAN_RESPONSE_TCA: + /* fall through */ + case legacy_hal::NAN_RESPONSE_STATS: + /* fall through */ + case legacy_hal::NAN_RESPONSE_ERROR: + /* fall through */ + default: + LOG(ERROR) << "Unknown or unhandled response type: " + << msg.response_type; + return; + } + }; + + callback_handlers.on_event_disc_eng_event = + [weak_ptr_this](const legacy_hal::NanDiscEngEventInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + NanClusterEventInd hidl_struct; + // event types defined identically - hence can be cast + hidl_struct.eventType = (NanClusterEventType)msg.event_type; + hidl_struct.addr = msg.data.mac_addr.addr; + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventClusterEvent(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_disabled = + [weak_ptr_this](const legacy_hal::NanDisabledInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus status; + hidl_struct_util::convertToWifiNanStatus( + msg.reason, msg.nan_reason, sizeof(msg.nan_reason), &status); + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventDisabled(status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_publish_terminated = + [weak_ptr_this](const legacy_hal::NanPublishTerminatedInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus status; + hidl_struct_util::convertToWifiNanStatus( + msg.reason, msg.nan_reason, sizeof(msg.nan_reason), &status); + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventPublishTerminated(msg.publish_id, status) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_subscribe_terminated = + [weak_ptr_this](const legacy_hal::NanSubscribeTerminatedInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus status; + hidl_struct_util::convertToWifiNanStatus( + msg.reason, msg.nan_reason, sizeof(msg.nan_reason), &status); + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback + ->eventSubscribeTerminated(msg.subscribe_id, status) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_match = + [weak_ptr_this](const legacy_hal::NanMatchInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + NanMatchInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanMatchIndToHidl( + msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventMatch(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_match_expired = + [weak_ptr_this](const legacy_hal::NanMatchExpiredInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback + ->eventMatchExpired(msg.publish_subscribe_id, + msg.requestor_instance_id) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_followup = + [weak_ptr_this](const legacy_hal::NanFollowupInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + NanFollowupReceivedInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanFollowupIndToHidl( + msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventFollowupReceived(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_transmit_follow_up = + [weak_ptr_this](const legacy_hal::NanTransmitFollowupInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + WifiNanStatus status; + hidl_struct_util::convertToWifiNanStatus( + msg.reason, msg.nan_reason, sizeof(msg.nan_reason), &status); + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventTransmitFollowup(msg.id, status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_data_path_request = + [weak_ptr_this](const legacy_hal::NanDataPathRequestInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + NanDataPathRequestInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanDataPathRequestIndToHidl( + msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventDataPathRequest(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_data_path_confirm = + [weak_ptr_this](const legacy_hal::NanDataPathConfirmInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + V1_2::NanDataPathConfirmInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanDataPathConfirmIndToHidl( + msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : + shared_ptr_this->getEventCallbacks_1_2()) { + if (!callback->eventDataPathConfirm_1_2(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + callback_handlers.on_event_data_path_end = + [weak_ptr_this](const legacy_hal::NanDataPathEndInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + for (int i = 0; i < msg.num_ndp_instances; ++i) { + if (!callback + ->eventDataPathTerminated(msg.ndp_instance_id[i]) + .isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + } + }; + + callback_handlers.on_event_beacon_sdf_payload = + [weak_ptr_this](const legacy_hal::NanBeaconSdfPayloadInd& /* msg */) { + LOG(ERROR) << "on_event_beacon_sdf_payload - should not be called"; + }; + + callback_handlers.on_event_range_request = + [weak_ptr_this](const legacy_hal::NanRangeRequestInd& /* msg */) { + LOG(ERROR) << "on_event_range_request - should not be called"; + }; + + callback_handlers.on_event_range_report = + [weak_ptr_this](const legacy_hal::NanRangeReportInd& /* msg */) { + LOG(ERROR) << "on_event_range_report - should not be called"; + }; + + callback_handlers + .on_event_schedule_update = [weak_ptr_this]( + const legacy_hal:: + NanDataPathScheduleUpdateInd& msg) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + V1_2::NanDataPathScheduleUpdateInd hidl_struct; + if (!hidl_struct_util::convertLegacyNanDataPathScheduleUpdateIndToHidl( + msg, &hidl_struct)) { + LOG(ERROR) << "Failed to convert nan capabilities response"; + return; + } + + for (const auto& callback : shared_ptr_this->getEventCallbacks_1_2()) { + if (!callback->eventDataPathScheduleUpdate(hidl_struct).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanRegisterCallbackHandlers(ifname_, + callback_handlers); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) << "Failed to register nan callbacks. Invalidating object"; + invalidate(); + } + + // Register for iface state toggle events. + iface_util::IfaceEventHandlers event_handlers = {}; + event_handlers.on_state_toggle_off_on = + [weak_ptr_this](const std::string& /* iface_name */) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + // Tell framework that NAN has been disabled. + WifiNanStatus status = { + NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""}; + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->eventDisabled(status).isOk()) { + LOG(ERROR) << "Failed to invoke the callback"; + } + } + }; + iface_util_.lock()->registerIfaceEventHandlers(ifname_, event_handlers); +} + +void WifiNanIface::invalidate() { + // send commands to HAL to actually disable and destroy interfaces + legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF); + legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0"); + legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFD, "aware_data1"); + iface_util_.lock()->unregisterIfaceEventHandlers(ifname_); + legacy_hal_.reset(); + event_cb_handler_.invalidate(); + event_cb_handler_1_2_.invalidate(); + is_valid_ = false; +} + +bool WifiNanIface::isValid() { return is_valid_; } + +std::string WifiNanIface::getName() { return ifname_; } + +std::set<sp<V1_0::IWifiNanIfaceEventCallback>> +WifiNanIface::getEventCallbacks() { + return event_cb_handler_.getCallbacks(); +} + +std::set<sp<V1_2::IWifiNanIfaceEventCallback>> +WifiNanIface::getEventCallbacks_1_2() { + return event_cb_handler_1_2_.getCallbacks(); +} + +Return<void> WifiNanIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getNameInternal, hidl_status_cb); +} + +Return<void> WifiNanIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getTypeInternal, hidl_status_cb); +} + +Return<void> WifiNanIface::registerEventCallback( + const sp<V1_0::IWifiNanIfaceEventCallback>& callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::registerEventCallbackInternal, + hidl_status_cb, callback); +} + +Return<void> WifiNanIface::getCapabilitiesRequest( + uint16_t cmd_id, getCapabilitiesRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::getCapabilitiesRequestInternal, + hidl_status_cb, cmd_id); +} + +Return<void> WifiNanIface::enableRequest(uint16_t cmd_id, + const NanEnableRequest& msg, + enableRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequestInternal, hidl_status_cb, + cmd_id, msg); +} + +Return<void> WifiNanIface::configRequest(uint16_t cmd_id, + const NanConfigRequest& msg, + configRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequestInternal, hidl_status_cb, + cmd_id, msg); +} + +Return<void> WifiNanIface::disableRequest(uint16_t cmd_id, + disableRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::disableRequestInternal, + hidl_status_cb, cmd_id); +} + +Return<void> WifiNanIface::startPublishRequest( + uint16_t cmd_id, const NanPublishRequest& msg, + startPublishRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::startPublishRequestInternal, + hidl_status_cb, cmd_id, msg); +} + +Return<void> WifiNanIface::stopPublishRequest( + uint16_t cmd_id, uint8_t sessionId, stopPublishRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::stopPublishRequestInternal, + hidl_status_cb, cmd_id, sessionId); +} + +Return<void> WifiNanIface::startSubscribeRequest( + uint16_t cmd_id, const NanSubscribeRequest& msg, + startSubscribeRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::startSubscribeRequestInternal, + hidl_status_cb, cmd_id, msg); +} + +Return<void> WifiNanIface::stopSubscribeRequest( + uint16_t cmd_id, uint8_t sessionId, + stopSubscribeRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::stopSubscribeRequestInternal, + hidl_status_cb, cmd_id, sessionId); +} + +Return<void> WifiNanIface::transmitFollowupRequest( + uint16_t cmd_id, const NanTransmitFollowupRequest& msg, + transmitFollowupRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::transmitFollowupRequestInternal, + hidl_status_cb, cmd_id, msg); +} + +Return<void> WifiNanIface::createDataInterfaceRequest( + uint16_t cmd_id, const hidl_string& iface_name, + createDataInterfaceRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::createDataInterfaceRequestInternal, + hidl_status_cb, cmd_id, iface_name); +} + +Return<void> WifiNanIface::deleteDataInterfaceRequest( + uint16_t cmd_id, const hidl_string& iface_name, + deleteDataInterfaceRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::deleteDataInterfaceRequestInternal, + hidl_status_cb, cmd_id, iface_name); +} + +Return<void> WifiNanIface::initiateDataPathRequest( + uint16_t cmd_id, const NanInitiateDataPathRequest& msg, + initiateDataPathRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::initiateDataPathRequestInternal, + hidl_status_cb, cmd_id, msg); +} + +Return<void> WifiNanIface::respondToDataPathIndicationRequest( + uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg, + respondToDataPathIndicationRequest_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::respondToDataPathIndicationRequestInternal, + hidl_status_cb, cmd_id, msg); +} + +Return<void> WifiNanIface::terminateDataPathRequest( + uint16_t cmd_id, uint32_t ndpInstanceId, + terminateDataPathRequest_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::terminateDataPathRequestInternal, + hidl_status_cb, cmd_id, ndpInstanceId); +} + +Return<void> WifiNanIface::registerEventCallback_1_2( + const sp<V1_2::IWifiNanIfaceEventCallback>& callback, + registerEventCallback_1_2_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::registerEventCallback_1_2Internal, + hidl_status_cb, callback); +} + +Return<void> WifiNanIface::enableRequest_1_2( + uint16_t cmd_id, const NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + enableRequest_1_2_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::enableRequest_1_2Internal, + hidl_status_cb, cmd_id, msg1, msg2); +} + +Return<void> WifiNanIface::configRequest_1_2( + uint16_t cmd_id, const NanConfigRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + configRequest_1_2_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiNanIface::configRequest_1_2Internal, + hidl_status_cb, cmd_id, msg1, msg2); +} + +std::pair<WifiStatus, std::string> WifiNanIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair<WifiStatus, IfaceType> WifiNanIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::NAN}; +} + +WifiStatus WifiNanIface::registerEventCallbackInternal( + const sp<V1_0::IWifiNanIfaceEventCallback>& callback) { + if (!event_cb_handler_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiNanIface::getCapabilitiesRequestInternal(uint16_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanGetCapabilities(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::enableRequestInternal( + uint16_t /* cmd_id */, const NanEnableRequest& /* msg */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::configRequestInternal( + uint16_t /* cmd_id */, const NanConfigRequest& /* msg */) { + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED); +} + +WifiStatus WifiNanIface::disableRequestInternal(uint16_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDisableRequest(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::startPublishRequestInternal( + uint16_t cmd_id, const NanPublishRequest& msg) { + legacy_hal::NanPublishRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanPublishRequestToLegacy(msg, + &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanPublishRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::stopPublishRequestInternal(uint16_t cmd_id, + uint8_t sessionId) { + legacy_hal::NanPublishCancelRequest legacy_msg; + legacy_msg.publish_id = sessionId; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanPublishCancelRequest(ifname_, cmd_id, + legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::startSubscribeRequestInternal( + uint16_t cmd_id, const NanSubscribeRequest& msg) { + legacy_hal::NanSubscribeRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanSubscribeRequestToLegacy( + msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanSubscribeRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::stopSubscribeRequestInternal(uint16_t cmd_id, + uint8_t sessionId) { + legacy_hal::NanSubscribeCancelRequest legacy_msg; + legacy_msg.subscribe_id = sessionId; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanSubscribeCancelRequest(ifname_, cmd_id, + legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::transmitFollowupRequestInternal( + uint16_t cmd_id, const NanTransmitFollowupRequest& msg) { + legacy_hal::NanTransmitFollowupRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanTransmitFollowupRequestToLegacy( + msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanTransmitFollowupRequest(ifname_, cmd_id, + legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::createDataInterfaceRequestInternal( + uint16_t cmd_id, const std::string& iface_name) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataInterfaceCreate(ifname_, cmd_id, iface_name); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::deleteDataInterfaceRequestInternal( + uint16_t cmd_id, const std::string& iface_name) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, cmd_id, iface_name); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::initiateDataPathRequestInternal( + uint16_t cmd_id, const NanInitiateDataPathRequest& msg) { + legacy_hal::NanDataPathInitiatorRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanDataPathInitiatorRequestToLegacy( + msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataRequestInitiator(ifname_, cmd_id, + legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::respondToDataPathIndicationRequestInternal( + uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg) { + legacy_hal::NanDataPathIndicationResponse legacy_msg; + if (!hidl_struct_util::convertHidlNanDataPathIndicationResponseToLegacy( + msg, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataIndicationResponse(ifname_, cmd_id, + legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} +WifiStatus WifiNanIface::terminateDataPathRequestInternal( + uint16_t cmd_id, uint32_t ndpInstanceId) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanDataEnd(ifname_, cmd_id, ndpInstanceId); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::registerEventCallback_1_2Internal( + const sp<V1_2::IWifiNanIfaceEventCallback>& callback) { + sp<V1_0::IWifiNanIfaceEventCallback> callback_1_0 = callback; + if (!event_cb_handler_.addCallback(callback_1_0)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + if (!event_cb_handler_1_2_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiNanIface::enableRequest_1_2Internal( + uint16_t cmd_id, const NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2) { + legacy_hal::NanEnableRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanEnableRequest_1_2ToLegacy( + msg1, msg2, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanEnableRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiNanIface::configRequest_1_2Internal( + uint16_t cmd_id, const NanConfigRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2) { + legacy_hal::NanConfigRequest legacy_msg; + if (!hidl_struct_util::convertHidlNanConfigRequest_1_2ToLegacy( + msg1, msg2, &legacy_msg)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->nanConfigRequest(ifname_, cmd_id, legacy_msg); + return createWifiStatusFromLegacyError(legacy_status); +} + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi_nan_iface.h b/wifi/1.0/wifi_nan_iface.h new file mode 100644 index 0000000..737be93 --- /dev/null +++ b/wifi/1.0/wifi_nan_iface.h @@ -0,0 +1,168 @@ +/* + * 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_NAN_IFACE_H_ +#define WIFI_NAN_IFACE_H_ + +#include <android-base/macros.h> +#include <android/hardware/wifi/1.0/IWifiNanIfaceEventCallback.h> +#include <android/hardware/wifi/1.2/IWifiNanIface.h> + +#include "hidl_callback_util.h" +#include "wifi_iface_util.h" +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a NAN Iface instance. + */ +class WifiNanIface : public V1_2::IWifiNanIface { + public: + WifiNanIface(const std::string& ifname, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::string getName(); + + // HIDL methods exposed. + Return<void> getName(getName_cb hidl_status_cb) override; + Return<void> getType(getType_cb hidl_status_cb) override; + Return<void> registerEventCallback( + const sp<V1_0::IWifiNanIfaceEventCallback>& callback, + registerEventCallback_cb hidl_status_cb) override; + Return<void> getCapabilitiesRequest( + uint16_t cmd_id, getCapabilitiesRequest_cb hidl_status_cb) override; + Return<void> enableRequest(uint16_t cmd_id, const NanEnableRequest& msg, + enableRequest_cb hidl_status_cb) override; + Return<void> configRequest(uint16_t cmd_id, const NanConfigRequest& msg, + configRequest_cb hidl_status_cb) override; + Return<void> disableRequest(uint16_t cmd_id, + disableRequest_cb hidl_status_cb) override; + Return<void> startPublishRequest( + uint16_t cmd_id, const NanPublishRequest& msg, + startPublishRequest_cb hidl_status_cb) override; + Return<void> stopPublishRequest( + uint16_t cmd_id, uint8_t sessionId, + stopPublishRequest_cb hidl_status_cb) override; + Return<void> startSubscribeRequest( + uint16_t cmd_id, const NanSubscribeRequest& msg, + startSubscribeRequest_cb hidl_status_cb) override; + Return<void> stopSubscribeRequest( + uint16_t cmd_id, uint8_t sessionId, + stopSubscribeRequest_cb hidl_status_cb) override; + Return<void> transmitFollowupRequest( + uint16_t cmd_id, const NanTransmitFollowupRequest& msg, + transmitFollowupRequest_cb hidl_status_cb) override; + Return<void> createDataInterfaceRequest( + uint16_t cmd_id, const hidl_string& iface_name, + createDataInterfaceRequest_cb hidl_status_cb) override; + Return<void> deleteDataInterfaceRequest( + uint16_t cmd_id, const hidl_string& iface_name, + deleteDataInterfaceRequest_cb hidl_status_cb) override; + Return<void> initiateDataPathRequest( + uint16_t cmd_id, const NanInitiateDataPathRequest& msg, + initiateDataPathRequest_cb hidl_status_cb) override; + Return<void> respondToDataPathIndicationRequest( + uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg, + respondToDataPathIndicationRequest_cb hidl_status_cb) override; + Return<void> terminateDataPathRequest( + uint16_t cmd_id, uint32_t ndpInstanceId, + terminateDataPathRequest_cb hidl_status_cb) override; + + Return<void> registerEventCallback_1_2( + const sp<V1_2::IWifiNanIfaceEventCallback>& callback, + registerEventCallback_1_2_cb hidl_status_cb) override; + Return<void> enableRequest_1_2( + uint16_t cmd_id, const NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + enableRequest_1_2_cb hidl_status_cb) override; + Return<void> configRequest_1_2( + uint16_t cmd_id, const NanConfigRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2, + configRequest_1_2_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair<WifiStatus, std::string> getNameInternal(); + std::pair<WifiStatus, IfaceType> getTypeInternal(); + WifiStatus registerEventCallbackInternal( + const sp<V1_0::IWifiNanIfaceEventCallback>& callback); + WifiStatus getCapabilitiesRequestInternal(uint16_t cmd_id); + WifiStatus enableRequestInternal(uint16_t cmd_id, + const NanEnableRequest& msg); + WifiStatus configRequestInternal(uint16_t cmd_id, + const NanConfigRequest& msg); + WifiStatus disableRequestInternal(uint16_t cmd_id); + WifiStatus startPublishRequestInternal(uint16_t cmd_id, + const NanPublishRequest& msg); + WifiStatus stopPublishRequestInternal(uint16_t cmd_id, uint8_t sessionId); + WifiStatus startSubscribeRequestInternal(uint16_t cmd_id, + const NanSubscribeRequest& msg); + WifiStatus stopSubscribeRequestInternal(uint16_t cmd_id, uint8_t sessionId); + WifiStatus transmitFollowupRequestInternal( + uint16_t cmd_id, const NanTransmitFollowupRequest& msg); + WifiStatus createDataInterfaceRequestInternal( + uint16_t cmd_id, const std::string& iface_name); + WifiStatus deleteDataInterfaceRequestInternal( + uint16_t cmd_id, const std::string& iface_name); + WifiStatus initiateDataPathRequestInternal( + uint16_t cmd_id, const NanInitiateDataPathRequest& msg); + WifiStatus respondToDataPathIndicationRequestInternal( + uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg); + WifiStatus terminateDataPathRequestInternal(uint16_t cmd_id, + uint32_t ndpInstanceId); + + WifiStatus registerEventCallback_1_2Internal( + const sp<V1_2::IWifiNanIfaceEventCallback>& callback); + WifiStatus enableRequest_1_2Internal( + uint16_t cmd_id, const NanEnableRequest& msg1, + const V1_2::NanConfigRequestSupplemental& msg2); + WifiStatus configRequest_1_2Internal( + uint16_t cmd_id, const NanConfigRequest& msg, + const V1_2::NanConfigRequestSupplemental& msg2); + + // all 1_0 and descendant callbacks + std::set<sp<V1_0::IWifiNanIfaceEventCallback>> getEventCallbacks(); + // all 1_2 and descendant callbacks + std::set<sp<V1_2::IWifiNanIfaceEventCallback>> getEventCallbacks_1_2(); + + std::string ifname_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_; + bool is_valid_; + hidl_callback_util::HidlCallbackHandler<V1_0::IWifiNanIfaceEventCallback> + event_cb_handler_; + hidl_callback_util::HidlCallbackHandler<V1_2::IWifiNanIfaceEventCallback> + event_cb_handler_1_2_; + + DISALLOW_COPY_AND_ASSIGN(WifiNanIface); +}; + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_NAN_IFACE_H_ diff --git a/wifi/1.0/wifi_p2p_iface.cpp b/wifi/1.0/wifi_p2p_iface.cpp new file mode 100644 index 0000000..b5d5886 --- /dev/null +++ b/wifi/1.0/wifi_p2p_iface.cpp @@ -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. + */ + +#include <android-base/logging.h> + +#include "hidl_return_util.h" +#include "wifi_p2p_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiP2pIface::WifiP2pIface( + const std::string& ifname, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal) + : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {} + +void WifiP2pIface::invalidate() { + legacy_hal_.reset(); + is_valid_ = false; +} + +bool WifiP2pIface::isValid() { return is_valid_; } + +std::string WifiP2pIface::getName() { return ifname_; } + +Return<void> WifiP2pIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiP2pIface::getNameInternal, hidl_status_cb); +} + +Return<void> WifiP2pIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiP2pIface::getTypeInternal, hidl_status_cb); +} + +std::pair<WifiStatus, std::string> WifiP2pIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair<WifiStatus, IfaceType> WifiP2pIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::P2P}; +} + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi_p2p_iface.h b/wifi/1.0/wifi_p2p_iface.h new file mode 100644 index 0000000..8a7207a --- /dev/null +++ b/wifi/1.0/wifi_p2p_iface.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_P2P_IFACE_H_ +#define WIFI_P2P_IFACE_H_ + +#include <android-base/macros.h> +#include <android/hardware/wifi/1.0/IWifiP2pIface.h> + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a P2P Iface instance. + */ +class WifiP2pIface : public V1_0::IWifiP2pIface { + public: + WifiP2pIface(const std::string& ifname, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::string getName(); + + // HIDL methods exposed. + Return<void> getName(getName_cb hidl_status_cb) override; + Return<void> getType(getType_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair<WifiStatus, std::string> getNameInternal(); + std::pair<WifiStatus, IfaceType> getTypeInternal(); + + std::string ifname_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + bool is_valid_; + + DISALLOW_COPY_AND_ASSIGN(WifiP2pIface); +}; + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_P2P_IFACE_H_ diff --git a/wifi/1.0/wifi_rtt_controller.cpp b/wifi/1.0/wifi_rtt_controller.cpp new file mode 100644 index 0000000..3dcbee6 --- /dev/null +++ b/wifi/1.0/wifi_rtt_controller.cpp @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/logging.h> + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_rtt_controller.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiRttController::WifiRttController( + const std::string& iface_name, const sp<IWifiIface>& bound_iface, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal) + : ifname_(iface_name), + bound_iface_(bound_iface), + legacy_hal_(legacy_hal), + is_valid_(true) {} + +void WifiRttController::invalidate() { + legacy_hal_.reset(); + event_callbacks_.clear(); + is_valid_ = false; +} + +bool WifiRttController::isValid() { return is_valid_; } + +std::vector<sp<IWifiRttControllerEventCallback>> +WifiRttController::getEventCallbacks() { + return event_callbacks_; +} + +std::string WifiRttController::getIfaceName() { return ifname_; } + +Return<void> WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getBoundIfaceInternal, hidl_status_cb); +} + +Return<void> WifiRttController::registerEventCallback( + const sp<IWifiRttControllerEventCallback>& callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::registerEventCallbackInternal, + hidl_status_cb, callback); +} + +Return<void> WifiRttController::rangeRequest( + uint32_t cmd_id, const hidl_vec<RttConfig>& rtt_configs, + rangeRequest_cb hidl_status_cb) { + return validateAndCall(this, + WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::rangeRequestInternal, + hidl_status_cb, cmd_id, rtt_configs); +} + +Return<void> WifiRttController::rangeCancel( + uint32_t cmd_id, const hidl_vec<hidl_array<uint8_t, 6>>& addrs, + rangeCancel_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::rangeCancelInternal, hidl_status_cb, cmd_id, addrs); +} + +Return<void> WifiRttController::getCapabilities( + getCapabilities_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getCapabilitiesInternal, hidl_status_cb); +} + +Return<void> WifiRttController::setLci(uint32_t cmd_id, + const RttLciInformation& lci, + setLci_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::setLciInternal, hidl_status_cb, cmd_id, lci); +} + +Return<void> WifiRttController::setLcr(uint32_t cmd_id, + const RttLcrInformation& lcr, + setLcr_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::setLcrInternal, hidl_status_cb, cmd_id, lcr); +} + +Return<void> WifiRttController::getResponderInfo( + getResponderInfo_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::getResponderInfoInternal, hidl_status_cb); +} + +Return<void> WifiRttController::enableResponder( + uint32_t cmd_id, const WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, const RttResponder& info, + enableResponder_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::enableResponderInternal, hidl_status_cb, cmd_id, + channel_hint, max_duration_seconds, info); +} + +Return<void> WifiRttController::disableResponder( + uint32_t cmd_id, disableResponder_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, + &WifiRttController::disableResponderInternal, hidl_status_cb, cmd_id); +} + +std::pair<WifiStatus, sp<IWifiIface>> +WifiRttController::getBoundIfaceInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), bound_iface_}; +} + +WifiStatus WifiRttController::registerEventCallbackInternal( + const sp<IWifiRttControllerEventCallback>& callback) { + // TODO(b/31632518): remove the callback when the client is destroyed + event_callbacks_.emplace_back(callback); + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +WifiStatus WifiRttController::rangeRequestInternal( + uint32_t cmd_id, const std::vector<RttConfig>& rtt_configs) { + std::vector<legacy_hal::wifi_rtt_config> legacy_configs; + if (!hidl_struct_util::convertHidlVectorOfRttConfigToLegacy( + rtt_configs, &legacy_configs)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + android::wp<WifiRttController> weak_ptr_this(this); + const auto& on_results_callback = + [weak_ptr_this]( + legacy_hal::wifi_request_id id, + const std::vector<const legacy_hal::wifi_rtt_result*>& results) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + std::vector<RttResult> hidl_results; + if (!hidl_struct_util::convertLegacyVectorOfRttResultToHidl( + results, &hidl_results)) { + LOG(ERROR) << "Failed to convert rtt results to HIDL structs"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + callback->onResults(id, hidl_results); + } + }; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->startRttRangeRequest( + ifname_, cmd_id, legacy_configs, on_results_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiRttController::rangeCancelInternal( + uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs) { + std::vector<std::array<uint8_t, 6>> legacy_addrs; + for (const auto& addr : addrs) { + legacy_addrs.push_back(addr); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->cancelRttRangeRequest(ifname_, cmd_id, + legacy_addrs); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, RttCapabilities> +WifiRttController::getCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_rtt_capabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = + legacy_hal_.lock()->getRttCapabilities(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + RttCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyRttCapabilitiesToHidl(legacy_caps, + &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +WifiStatus WifiRttController::setLciInternal(uint32_t cmd_id, + const RttLciInformation& lci) { + legacy_hal::wifi_lci_information legacy_lci; + if (!hidl_struct_util::convertHidlRttLciInformationToLegacy(lci, + &legacy_lci)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setRttLci(ifname_, cmd_id, legacy_lci); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiRttController::setLcrInternal(uint32_t cmd_id, + const RttLcrInformation& lcr) { + legacy_hal::wifi_lcr_information legacy_lcr; + if (!hidl_struct_util::convertHidlRttLcrInformationToLegacy(lcr, + &legacy_lcr)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setRttLcr(ifname_, cmd_id, legacy_lcr); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, RttResponder> +WifiRttController::getResponderInfoInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_rtt_responder legacy_responder; + std::tie(legacy_status, legacy_responder) = + legacy_hal_.lock()->getRttResponderInfo(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + RttResponder hidl_responder; + if (!hidl_struct_util::convertLegacyRttResponderToHidl(legacy_responder, + &hidl_responder)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_responder}; +} + +WifiStatus WifiRttController::enableResponderInternal( + uint32_t cmd_id, const WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, const RttResponder& info) { + legacy_hal::wifi_channel_info legacy_channel_info; + if (!hidl_struct_util::convertHidlWifiChannelInfoToLegacy( + channel_hint, &legacy_channel_info)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_rtt_responder legacy_responder; + if (!hidl_struct_util::convertHidlRttResponderToLegacy(info, + &legacy_responder)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->enableRttResponder( + ifname_, cmd_id, legacy_channel_info, max_duration_seconds, + legacy_responder); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiRttController::disableResponderInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->disableRttResponder(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi_rtt_controller.h b/wifi/1.0/wifi_rtt_controller.h new file mode 100644 index 0000000..eedd22a --- /dev/null +++ b/wifi/1.0/wifi_rtt_controller.h @@ -0,0 +1,106 @@ +/* + * 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_RTT_CONTROLLER_H_ +#define WIFI_RTT_CONTROLLER_H_ + +#include <android-base/macros.h> +#include <android/hardware/wifi/1.0/IWifiIface.h> +#include <android/hardware/wifi/1.0/IWifiRttController.h> +#include <android/hardware/wifi/1.0/IWifiRttControllerEventCallback.h> + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { + +/** + * HIDL interface object used to control all RTT operations. + */ +class WifiRttController : public V1_0::IWifiRttController { + public: + WifiRttController( + const std::string& iface_name, const sp<IWifiIface>& bound_iface, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::vector<sp<IWifiRttControllerEventCallback>> getEventCallbacks(); + std::string getIfaceName(); + + // HIDL methods exposed. + Return<void> getBoundIface(getBoundIface_cb hidl_status_cb) override; + Return<void> registerEventCallback( + const sp<IWifiRttControllerEventCallback>& callback, + registerEventCallback_cb hidl_status_cb) override; + Return<void> rangeRequest(uint32_t cmd_id, + const hidl_vec<RttConfig>& rtt_configs, + rangeRequest_cb hidl_status_cb) override; + Return<void> rangeCancel(uint32_t cmd_id, + const hidl_vec<hidl_array<uint8_t, 6>>& addrs, + rangeCancel_cb hidl_status_cb) override; + Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override; + Return<void> setLci(uint32_t cmd_id, const RttLciInformation& lci, + setLci_cb hidl_status_cb) override; + Return<void> setLcr(uint32_t cmd_id, const RttLcrInformation& lcr, + setLcr_cb hidl_status_cb) override; + Return<void> getResponderInfo(getResponderInfo_cb hidl_status_cb) override; + Return<void> enableResponder(uint32_t cmd_id, + const WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const RttResponder& info, + enableResponder_cb hidl_status_cb) override; + Return<void> disableResponder(uint32_t cmd_id, + disableResponder_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair<WifiStatus, sp<IWifiIface>> getBoundIfaceInternal(); + WifiStatus registerEventCallbackInternal( + const sp<IWifiRttControllerEventCallback>& callback); + WifiStatus rangeRequestInternal(uint32_t cmd_id, + const std::vector<RttConfig>& rtt_configs); + WifiStatus rangeCancelInternal( + uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs); + std::pair<WifiStatus, RttCapabilities> getCapabilitiesInternal(); + WifiStatus setLciInternal(uint32_t cmd_id, const RttLciInformation& lci); + WifiStatus setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr); + std::pair<WifiStatus, RttResponder> getResponderInfoInternal(); + WifiStatus enableResponderInternal(uint32_t cmd_id, + const WifiChannelInfo& channel_hint, + uint32_t max_duration_seconds, + const RttResponder& info); + WifiStatus disableResponderInternal(uint32_t cmd_id); + + std::string ifname_; + sp<IWifiIface> bound_iface_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + std::vector<sp<IWifiRttControllerEventCallback>> event_callbacks_; + bool is_valid_; + + DISALLOW_COPY_AND_ASSIGN(WifiRttController); +}; + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_RTT_CONTROLLER_H_ diff --git a/wifi/1.0/wifi_sta_iface.cpp b/wifi/1.0/wifi_sta_iface.cpp new file mode 100644 index 0000000..a6539e5 --- /dev/null +++ b/wifi/1.0/wifi_sta_iface.cpp @@ -0,0 +1,647 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/logging.h> + +#include "hidl_return_util.h" +#include "hidl_struct_util.h" +#include "wifi_sta_iface.h" +#include "wifi_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using hidl_return_util::validateAndCall; + +WifiStaIface::WifiStaIface( + const std::string& ifname, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util) + : ifname_(ifname), + legacy_hal_(legacy_hal), + iface_util_(iface_util), + is_valid_(true) { + // Turn on DFS channel usage for STA iface. + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setDfsFlag(ifname_, true); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + LOG(ERROR) + << "Failed to set DFS flag; DFS channels may be unavailable."; + } +} + +void WifiStaIface::invalidate() { + legacy_hal_.reset(); + event_cb_handler_.invalidate(); + is_valid_ = false; +} + +bool WifiStaIface::isValid() { return is_valid_; } + +std::string WifiStaIface::getName() { return ifname_; } + +std::set<sp<IWifiStaIfaceEventCallback>> WifiStaIface::getEventCallbacks() { + return event_cb_handler_.getCallbacks(); +} + +Return<void> WifiStaIface::getName(getName_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getNameInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::getType(getType_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getTypeInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::registerEventCallback( + const sp<IWifiStaIfaceEventCallback>& callback, + registerEventCallback_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::registerEventCallbackInternal, + hidl_status_cb, callback); +} + +Return<void> WifiStaIface::getCapabilities(getCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getCapabilitiesInternal, + hidl_status_cb); +} + +Return<void> WifiStaIface::getApfPacketFilterCapabilities( + getApfPacketFilterCapabilities_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getApfPacketFilterCapabilitiesInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::installApfPacketFilter( + uint32_t cmd_id, const hidl_vec<uint8_t>& program, + installApfPacketFilter_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::installApfPacketFilterInternal, + hidl_status_cb, cmd_id, program); +} + +Return<void> WifiStaIface::readApfPacketFilterData( + readApfPacketFilterData_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::readApfPacketFilterDataInternal, + hidl_status_cb); +} + +Return<void> WifiStaIface::getBackgroundScanCapabilities( + getBackgroundScanCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getBackgroundScanCapabilitiesInternal, + hidl_status_cb); +} + +Return<void> WifiStaIface::getValidFrequenciesForBand( + WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getValidFrequenciesForBandInternal, + hidl_status_cb, band); +} + +Return<void> WifiStaIface::startBackgroundScan( + uint32_t cmd_id, const StaBackgroundScanParameters& params, + startBackgroundScan_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startBackgroundScanInternal, + hidl_status_cb, cmd_id, params); +} + +Return<void> WifiStaIface::stopBackgroundScan( + uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::stopBackgroundScanInternal, + hidl_status_cb, cmd_id); +} + +Return<void> WifiStaIface::enableLinkLayerStatsCollection( + bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::enableLinkLayerStatsCollectionInternal, hidl_status_cb, + debug); +} + +Return<void> WifiStaIface::disableLinkLayerStatsCollection( + disableLinkLayerStatsCollection_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::disableLinkLayerStatsCollectionInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::getLinkLayerStats( + getLinkLayerStats_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal, + hidl_status_cb); +} + +Return<void> WifiStaIface::getLinkLayerStats_1_3( + getLinkLayerStats_1_3_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getLinkLayerStatsInternal_1_3, + hidl_status_cb); +} + +Return<void> WifiStaIface::startRssiMonitoring( + uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi, + startRssiMonitoring_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startRssiMonitoringInternal, + hidl_status_cb, cmd_id, max_rssi, min_rssi); +} + +Return<void> WifiStaIface::stopRssiMonitoring( + uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::stopRssiMonitoringInternal, + hidl_status_cb, cmd_id); +} + +Return<void> WifiStaIface::getRoamingCapabilities( + getRoamingCapabilities_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getRoamingCapabilitiesInternal, + hidl_status_cb); +} + +Return<void> WifiStaIface::configureRoaming( + const StaRoamingConfig& config, configureRoaming_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::configureRoamingInternal, + hidl_status_cb, config); +} + +Return<void> WifiStaIface::setRoamingState(StaRoamingState state, + setRoamingState_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setRoamingStateInternal, + hidl_status_cb, state); +} + +Return<void> WifiStaIface::enableNdOffload(bool enable, + enableNdOffload_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::enableNdOffloadInternal, + hidl_status_cb, enable); +} + +Return<void> WifiStaIface::startSendingKeepAlivePackets( + uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data, + uint16_t ether_type, const hidl_array<uint8_t, 6>& src_address, + const hidl_array<uint8_t, 6>& dst_address, uint32_t period_in_ms, + startSendingKeepAlivePackets_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startSendingKeepAlivePacketsInternal, + hidl_status_cb, cmd_id, ip_packet_data, ether_type, + src_address, dst_address, period_in_ms); +} + +Return<void> WifiStaIface::stopSendingKeepAlivePackets( + uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::stopSendingKeepAlivePacketsInternal, + hidl_status_cb, cmd_id); +} + +Return<void> WifiStaIface::setScanningMacOui( + const hidl_array<uint8_t, 3>& oui, setScanningMacOui_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setScanningMacOuiInternal, + hidl_status_cb, oui); +} + +Return<void> WifiStaIface::startDebugPacketFateMonitoring( + startDebugPacketFateMonitoring_cb hidl_status_cb) { + return validateAndCall( + this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::startDebugPacketFateMonitoringInternal, hidl_status_cb); +} + +Return<void> WifiStaIface::getDebugTxPacketFates( + getDebugTxPacketFates_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getDebugTxPacketFatesInternal, + hidl_status_cb); +} + +Return<void> WifiStaIface::getDebugRxPacketFates( + getDebugRxPacketFates_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getDebugRxPacketFatesInternal, + hidl_status_cb); +} + +Return<void> WifiStaIface::setMacAddress(const hidl_array<uint8_t, 6>& mac, + setMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::setMacAddressInternal, hidl_status_cb, + mac); +} + +Return<void> WifiStaIface::getFactoryMacAddress( + getFactoryMacAddress_cb hidl_status_cb) { + return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID, + &WifiStaIface::getFactoryMacAddressInternal, + hidl_status_cb); +} + +std::pair<WifiStatus, std::string> WifiStaIface::getNameInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_}; +} + +std::pair<WifiStatus, IfaceType> WifiStaIface::getTypeInternal() { + return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::STA}; +} + +WifiStatus WifiStaIface::registerEventCallbackInternal( + const sp<IWifiStaIfaceEventCallback>& callback) { + if (!event_cb_handler_.addCallback(callback)) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + uint32_t legacy_feature_set; + std::tie(legacy_status, legacy_feature_set) = + legacy_hal_.lock()->getSupportedFeatureSet(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), 0}; + } + uint32_t legacy_logger_feature_set; + std::tie(legacy_status, legacy_logger_feature_set) = + legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + // some devices don't support querying logger feature set + legacy_logger_feature_set = 0; + } + uint32_t hidl_caps; + if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities( + legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +std::pair<WifiStatus, StaApfPacketFilterCapabilities> +WifiStaIface::getApfPacketFilterCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::PacketFilterCapabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = + legacy_hal_.lock()->getPacketFilterCapabilities(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + StaApfPacketFilterCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyApfCapabilitiesToHidl(legacy_caps, + &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +WifiStatus WifiStaIface::installApfPacketFilterInternal( + uint32_t /* cmd_id */, const std::vector<uint8_t>& program) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setPacketFilter(ifname_, program); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, std::vector<uint8_t>> +WifiStaIface::readApfPacketFilterDataInternal() { + const std::pair<legacy_hal::wifi_error, std::vector<uint8_t>> + legacy_status_and_data = + legacy_hal_.lock()->readApfPacketFilterData(ifname_); + return {createWifiStatusFromLegacyError(legacy_status_and_data.first), + std::move(legacy_status_and_data.second)}; +} + +std::pair<WifiStatus, StaBackgroundScanCapabilities> +WifiStaIface::getBackgroundScanCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_gscan_capabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = + legacy_hal_.lock()->getGscanCapabilities(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + StaBackgroundScanCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyGscanCapabilitiesToHidl(legacy_caps, + &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +std::pair<WifiStatus, std::vector<WifiChannelInMhz>> +WifiStaIface::getValidFrequenciesForBandInternal(WifiBand band) { + static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), + "Size mismatch"); + legacy_hal::wifi_error legacy_status; + std::vector<uint32_t> valid_frequencies; + std::tie(legacy_status, valid_frequencies) = + legacy_hal_.lock()->getValidFrequenciesForBand( + ifname_, hidl_struct_util::convertHidlWifiBandToLegacy(band)); + return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies}; +} + +WifiStatus WifiStaIface::startBackgroundScanInternal( + uint32_t cmd_id, const StaBackgroundScanParameters& params) { + legacy_hal::wifi_scan_cmd_params legacy_params; + if (!hidl_struct_util::convertHidlGscanParamsToLegacy(params, + &legacy_params)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + android::wp<WifiStaIface> weak_ptr_this(this); + const auto& on_failure_callback = + [weak_ptr_this](legacy_hal::wifi_request_id id) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onBackgroundScanFailure(id).isOk()) { + LOG(ERROR) + << "Failed to invoke onBackgroundScanFailure callback"; + } + } + }; + const auto& on_results_callback = + [weak_ptr_this]( + legacy_hal::wifi_request_id id, + const std::vector<legacy_hal::wifi_cached_scan_results>& results) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + std::vector<StaScanData> hidl_scan_datas; + if (!hidl_struct_util:: + convertLegacyVectorOfCachedGscanResultsToHidl( + results, &hidl_scan_datas)) { + LOG(ERROR) << "Failed to convert scan results to HIDL structs"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onBackgroundScanResults(id, hidl_scan_datas) + .isOk()) { + LOG(ERROR) + << "Failed to invoke onBackgroundScanResults callback"; + } + } + }; + const auto& on_full_result_callback = [weak_ptr_this]( + legacy_hal::wifi_request_id id, + const legacy_hal:: + wifi_scan_result* result, + uint32_t buckets_scanned) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + StaScanResult hidl_scan_result; + if (!hidl_struct_util::convertLegacyGscanResultToHidl( + *result, true, &hidl_scan_result)) { + LOG(ERROR) << "Failed to convert full scan results to HIDL structs"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback + ->onBackgroundFullScanResult(id, buckets_scanned, + hidl_scan_result) + .isOk()) { + LOG(ERROR) + << "Failed to invoke onBackgroundFullScanResult callback"; + } + } + }; + legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startGscan( + ifname_, cmd_id, legacy_params, on_failure_callback, + on_results_callback, on_full_result_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::stopBackgroundScanInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->stopGscan(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(bool debug) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->enableLinkLayerStats(ifname_, debug); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->disableLinkLayerStats(ifname_); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, V1_0::StaLinkLayerStats> +WifiStaIface::getLinkLayerStatsInternal() { + return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}}; +} + +std::pair<WifiStatus, V1_3::StaLinkLayerStats> +WifiStaIface::getLinkLayerStatsInternal_1_3() { + legacy_hal::wifi_error legacy_status; + legacy_hal::LinkLayerStats legacy_stats; + std::tie(legacy_status, legacy_stats) = + legacy_hal_.lock()->getLinkLayerStats(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + V1_3::StaLinkLayerStats hidl_stats; + if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats, + &hidl_stats)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats}; +} + +WifiStatus WifiStaIface::startRssiMonitoringInternal(uint32_t cmd_id, + int32_t max_rssi, + int32_t min_rssi) { + android::wp<WifiStaIface> weak_ptr_this(this); + const auto& on_threshold_breached_callback = + [weak_ptr_this](legacy_hal::wifi_request_id id, + std::array<uint8_t, 6> bssid, int8_t rssi) { + const auto shared_ptr_this = weak_ptr_this.promote(); + if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) { + LOG(ERROR) << "Callback invoked on an invalid object"; + return; + } + for (const auto& callback : shared_ptr_this->getEventCallbacks()) { + if (!callback->onRssiThresholdBreached(id, bssid, rssi) + .isOk()) { + LOG(ERROR) + << "Failed to invoke onRssiThresholdBreached callback"; + } + } + }; + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->startRssiMonitoring(ifname_, cmd_id, max_rssi, + min_rssi, + on_threshold_breached_callback); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::stopRssiMonitoringInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->stopRssiMonitoring(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, StaRoamingCapabilities> +WifiStaIface::getRoamingCapabilitiesInternal() { + legacy_hal::wifi_error legacy_status; + legacy_hal::wifi_roaming_capabilities legacy_caps; + std::tie(legacy_status, legacy_caps) = + legacy_hal_.lock()->getRoamingCapabilities(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + StaRoamingCapabilities hidl_caps; + if (!hidl_struct_util::convertLegacyRoamingCapabilitiesToHidl(legacy_caps, + &hidl_caps)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps}; +} + +WifiStatus WifiStaIface::configureRoamingInternal( + const StaRoamingConfig& config) { + legacy_hal::wifi_roaming_config legacy_config; + if (!hidl_struct_util::convertHidlRoamingConfigToLegacy(config, + &legacy_config)) { + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS); + } + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->configureRoaming(ifname_, legacy_config); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::setRoamingStateInternal(StaRoamingState state) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->enableFirmwareRoaming( + ifname_, hidl_struct_util::convertHidlRoamingStateToLegacy(state)); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::enableNdOffloadInternal(bool enable) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->configureNdOffload(ifname_, enable); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal( + uint32_t cmd_id, const std::vector<uint8_t>& ip_packet_data, + uint16_t ether_type, const std::array<uint8_t, 6>& src_address, + const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->startSendingOffloadedPacket( + ifname_, cmd_id, ether_type, ip_packet_data, src_address, + dst_address, period_in_ms); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::stopSendingKeepAlivePacketsInternal(uint32_t cmd_id) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->stopSendingOffloadedPacket(ifname_, cmd_id); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::setScanningMacOuiInternal( + const std::array<uint8_t, 3>& oui) { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->setScanningMacOui(ifname_, oui); + return createWifiStatusFromLegacyError(legacy_status); +} + +WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() { + legacy_hal::wifi_error legacy_status = + legacy_hal_.lock()->startPktFateMonitoring(ifname_); + return createWifiStatusFromLegacyError(legacy_status); +} + +std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>> +WifiStaIface::getDebugTxPacketFatesInternal() { + legacy_hal::wifi_error legacy_status; + std::vector<legacy_hal::wifi_tx_report> legacy_fates; + std::tie(legacy_status, legacy_fates) = + legacy_hal_.lock()->getTxPktFates(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector<WifiDebugTxPacketFateReport> hidl_fates; + if (!hidl_struct_util::convertLegacyVectorOfDebugTxPacketFateToHidl( + legacy_fates, &hidl_fates)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates}; +} + +std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>> +WifiStaIface::getDebugRxPacketFatesInternal() { + legacy_hal::wifi_error legacy_status; + std::vector<legacy_hal::wifi_rx_report> legacy_fates; + std::tie(legacy_status, legacy_fates) = + legacy_hal_.lock()->getRxPktFates(ifname_); + if (legacy_status != legacy_hal::WIFI_SUCCESS) { + return {createWifiStatusFromLegacyError(legacy_status), {}}; + } + std::vector<WifiDebugRxPacketFateReport> hidl_fates; + if (!hidl_struct_util::convertLegacyVectorOfDebugRxPacketFateToHidl( + legacy_fates, &hidl_fates)) { + return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}}; + } + return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates}; +} + +WifiStatus WifiStaIface::setMacAddressInternal( + const std::array<uint8_t, 6>& mac) { + bool status = iface_util_.lock()->setMacAddress(ifname_, mac); + if (!status) { + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN); + } + return createWifiStatus(WifiStatusCode::SUCCESS); +} + +std::pair<WifiStatus, std::array<uint8_t, 6>> +WifiStaIface::getFactoryMacAddressInternal() { + std::array<uint8_t, 6> mac = + iface_util_.lock()->getFactoryMacAddress(ifname_); + return {createWifiStatus(WifiStatusCode::SUCCESS), mac}; +} + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi_sta_iface.h b/wifi/1.0/wifi_sta_iface.h new file mode 100644 index 0000000..9224939 --- /dev/null +++ b/wifi/1.0/wifi_sta_iface.h @@ -0,0 +1,179 @@ +/* + * 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_STA_IFACE_H_ +#define WIFI_STA_IFACE_H_ + +#include <android-base/macros.h> +#include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h> +#include <android/hardware/wifi/1.3/IWifiStaIface.h> + +#include "hidl_callback_util.h" +#include "wifi_iface_util.h" +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +/** + * HIDL interface object used to control a STA Iface instance. + */ +class WifiStaIface : public V1_3::IWifiStaIface { + public: + WifiStaIface(const std::string& ifname, + const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal, + const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util); + // Refer to |WifiChip::invalidate()|. + void invalidate(); + bool isValid(); + std::set<sp<IWifiStaIfaceEventCallback>> getEventCallbacks(); + std::string getName(); + + // HIDL methods exposed. + Return<void> getName(getName_cb hidl_status_cb) override; + Return<void> getType(getType_cb hidl_status_cb) override; + Return<void> registerEventCallback( + const sp<IWifiStaIfaceEventCallback>& callback, + registerEventCallback_cb hidl_status_cb) override; + Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override; + Return<void> getApfPacketFilterCapabilities( + getApfPacketFilterCapabilities_cb hidl_status_cb) override; + Return<void> installApfPacketFilter( + uint32_t cmd_id, const hidl_vec<uint8_t>& program, + installApfPacketFilter_cb hidl_status_cb) override; + Return<void> readApfPacketFilterData( + readApfPacketFilterData_cb hidl_status_cb) override; + Return<void> getBackgroundScanCapabilities( + getBackgroundScanCapabilities_cb hidl_status_cb) override; + Return<void> getValidFrequenciesForBand( + WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) override; + Return<void> startBackgroundScan( + uint32_t cmd_id, const StaBackgroundScanParameters& params, + startBackgroundScan_cb hidl_status_cb) override; + Return<void> stopBackgroundScan( + uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) override; + Return<void> enableLinkLayerStatsCollection( + bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) override; + Return<void> disableLinkLayerStatsCollection( + disableLinkLayerStatsCollection_cb hidl_status_cb) override; + Return<void> getLinkLayerStats( + getLinkLayerStats_cb hidl_status_cb) override; + Return<void> getLinkLayerStats_1_3( + getLinkLayerStats_1_3_cb hidl_status_cb) override; + Return<void> startRssiMonitoring( + uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi, + startRssiMonitoring_cb hidl_status_cb) override; + Return<void> stopRssiMonitoring( + uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) override; + Return<void> getRoamingCapabilities( + getRoamingCapabilities_cb hidl_status_cb) override; + Return<void> configureRoaming(const StaRoamingConfig& config, + configureRoaming_cb hidl_status_cb) override; + Return<void> setRoamingState(StaRoamingState state, + setRoamingState_cb hidl_status_cb) override; + Return<void> enableNdOffload(bool enable, + enableNdOffload_cb hidl_status_cb) override; + Return<void> startSendingKeepAlivePackets( + uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data, + uint16_t ether_type, const hidl_array<uint8_t, 6>& src_address, + const hidl_array<uint8_t, 6>& dst_address, uint32_t period_in_ms, + startSendingKeepAlivePackets_cb hidl_status_cb) override; + Return<void> stopSendingKeepAlivePackets( + uint32_t cmd_id, + stopSendingKeepAlivePackets_cb hidl_status_cb) override; + Return<void> setScanningMacOui( + const hidl_array<uint8_t, 3>& oui, + setScanningMacOui_cb hidl_status_cb) override; + Return<void> startDebugPacketFateMonitoring( + startDebugPacketFateMonitoring_cb hidl_status_cb) override; + Return<void> getDebugTxPacketFates( + getDebugTxPacketFates_cb hidl_status_cb) override; + Return<void> getDebugRxPacketFates( + getDebugRxPacketFates_cb hidl_status_cb) override; + Return<void> setMacAddress(const hidl_array<uint8_t, 6>& mac, + setMacAddress_cb hidl_status_cb) override; + Return<void> getFactoryMacAddress( + getFactoryMacAddress_cb hidl_status_cb) override; + + private: + // Corresponding worker functions for the HIDL methods. + std::pair<WifiStatus, std::string> getNameInternal(); + std::pair<WifiStatus, IfaceType> getTypeInternal(); + WifiStatus registerEventCallbackInternal( + const sp<IWifiStaIfaceEventCallback>& callback); + std::pair<WifiStatus, uint32_t> getCapabilitiesInternal(); + std::pair<WifiStatus, StaApfPacketFilterCapabilities> + getApfPacketFilterCapabilitiesInternal(); + WifiStatus installApfPacketFilterInternal( + uint32_t cmd_id, const std::vector<uint8_t>& program); + std::pair<WifiStatus, std::vector<uint8_t>> + readApfPacketFilterDataInternal(); + std::pair<WifiStatus, StaBackgroundScanCapabilities> + getBackgroundScanCapabilitiesInternal(); + std::pair<WifiStatus, std::vector<WifiChannelInMhz>> + getValidFrequenciesForBandInternal(WifiBand band); + WifiStatus startBackgroundScanInternal( + uint32_t cmd_id, const StaBackgroundScanParameters& params); + WifiStatus stopBackgroundScanInternal(uint32_t cmd_id); + WifiStatus enableLinkLayerStatsCollectionInternal(bool debug); + WifiStatus disableLinkLayerStatsCollectionInternal(); + std::pair<WifiStatus, V1_0::StaLinkLayerStats> getLinkLayerStatsInternal(); + std::pair<WifiStatus, V1_3::StaLinkLayerStats> + getLinkLayerStatsInternal_1_3(); + WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi, + int32_t min_rssi); + WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id); + std::pair<WifiStatus, StaRoamingCapabilities> + getRoamingCapabilitiesInternal(); + WifiStatus configureRoamingInternal(const StaRoamingConfig& config); + WifiStatus setRoamingStateInternal(StaRoamingState state); + WifiStatus enableNdOffloadInternal(bool enable); + WifiStatus startSendingKeepAlivePacketsInternal( + uint32_t cmd_id, const std::vector<uint8_t>& ip_packet_data, + uint16_t ether_type, const std::array<uint8_t, 6>& src_address, + const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms); + WifiStatus stopSendingKeepAlivePacketsInternal(uint32_t cmd_id); + WifiStatus setScanningMacOuiInternal(const std::array<uint8_t, 3>& oui); + WifiStatus startDebugPacketFateMonitoringInternal(); + std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>> + getDebugTxPacketFatesInternal(); + std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>> + getDebugRxPacketFatesInternal(); + WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac); + std::pair<WifiStatus, std::array<uint8_t, 6>> + getFactoryMacAddressInternal(); + + std::string ifname_; + std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_; + std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_; + bool is_valid_; + hidl_callback_util::HidlCallbackHandler<IWifiStaIfaceEventCallback> + event_cb_handler_; + + DISALLOW_COPY_AND_ASSIGN(WifiStaIface); +}; + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_STA_IFACE_H_ diff --git a/wifi/1.0/wifi_status_util.cpp b/wifi/1.0/wifi_status_util.cpp new file mode 100644 index 0000000..0a5bb13 --- /dev/null +++ b/wifi/1.0/wifi_status_util.cpp @@ -0,0 +1,106 @@ +/* + * 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_status_util.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { + +std::string legacyErrorToString(legacy_hal::wifi_error error) { + switch (error) { + case legacy_hal::WIFI_SUCCESS: + return "SUCCESS"; + case legacy_hal::WIFI_ERROR_UNINITIALIZED: + return "UNINITIALIZED"; + case legacy_hal::WIFI_ERROR_NOT_AVAILABLE: + return "NOT_AVAILABLE"; + case legacy_hal::WIFI_ERROR_NOT_SUPPORTED: + return "NOT_SUPPORTED"; + case legacy_hal::WIFI_ERROR_INVALID_ARGS: + return "INVALID_ARGS"; + case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID: + return "INVALID_REQUEST_ID"; + case legacy_hal::WIFI_ERROR_TIMED_OUT: + return "TIMED_OUT"; + case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS: + return "TOO_MANY_REQUESTS"; + case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY: + return "OUT_OF_MEMORY"; + case legacy_hal::WIFI_ERROR_BUSY: + return "BUSY"; + case legacy_hal::WIFI_ERROR_UNKNOWN: + return "UNKNOWN"; + } +} + +WifiStatus createWifiStatus(WifiStatusCode code, + const std::string& description) { + return {code, description}; +} + +WifiStatus createWifiStatus(WifiStatusCode code) { + return createWifiStatus(code, ""); +} + +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error, + const std::string& desc) { + switch (error) { + case legacy_hal::WIFI_ERROR_UNINITIALIZED: + case legacy_hal::WIFI_ERROR_NOT_AVAILABLE: + return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, desc); + + case legacy_hal::WIFI_ERROR_NOT_SUPPORTED: + return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED, desc); + + case legacy_hal::WIFI_ERROR_INVALID_ARGS: + case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID: + return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS, desc); + + case legacy_hal::WIFI_ERROR_TIMED_OUT: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, + desc + ", timed out"); + + case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, + desc + ", too many requests"); + + case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, + desc + ", out of memory"); + + case legacy_hal::WIFI_ERROR_BUSY: + return createWifiStatus(WifiStatusCode::ERROR_BUSY); + + case legacy_hal::WIFI_ERROR_NONE: + return createWifiStatus(WifiStatusCode::SUCCESS, desc); + + case legacy_hal::WIFI_ERROR_UNKNOWN: + return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown"); + } +} + +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error) { + return createWifiStatusFromLegacyError(error, ""); +} + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi/1.0/wifi_status_util.h b/wifi/1.0/wifi_status_util.h new file mode 100644 index 0000000..bc8baa9 --- /dev/null +++ b/wifi/1.0/wifi_status_util.h @@ -0,0 +1,45 @@ +/* + * 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_STATUS_UTIL_H_ +#define WIFI_STATUS_UTIL_H_ + +#include <android/hardware/wifi/1.0/IWifi.h> + +#include "wifi_legacy_hal.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace V1_3 { +namespace implementation { +using namespace android::hardware::wifi::V1_0; + +std::string legacyErrorToString(legacy_hal::wifi_error error); +WifiStatus createWifiStatus(WifiStatusCode code, + const std::string& description); +WifiStatus createWifiStatus(WifiStatusCode code); +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error, + const std::string& description); +WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error); + +} // namespace implementation +} // namespace V1_3 +} // namespace wifi +} // namespace hardware +} // namespace android + +#endif // WIFI_STATUS_UTIL_H_ |