Loading wifi/1.0/default/wifi_legacy_hal.cpp +161 −1 Original line number Diff line number Diff line Loading @@ -28,8 +28,13 @@ namespace wifi { namespace V1_0 { namespace implementation { namespace legacy_hal { // Constants used in the class. // 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; // Legacy HAL functions accept "C" style function pointers, so use global // functions to pass to the legacy HAL function and store the corresponding Loading Loading @@ -57,6 +62,27 @@ void onFirmwareMemoryDump(char* buffer, int buffer_size) { 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 onGscanEvent(wifi_request_id id, wifi_scan_event event) { 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 onGscanFullResult(wifi_request_id id, wifi_scan_result* result, uint32_t buckets_scanned) { if (on_gscan_full_result_internal_callback) { on_gscan_full_result_internal_callback(id, result, buckets_scanned); } } // End of the free-standing "C" style callbacks. WifiLegacyHal::WifiLegacyHal() Loading Loading @@ -206,6 +232,109 @@ wifi_error WifiLegacyHal::setPacketFilter(const std::vector<uint8_t>& program) { wlan_interface_handle_, program.data(), program.size()); } std::pair<wifi_error, wifi_gscan_capabilities> WifiLegacyHal::getGscanCapabilities() { wifi_gscan_capabilities caps; wifi_error status = global_func_table_.wifi_get_gscan_capabilities( wlan_interface_handle_, &caps); return {status, caps}; } wifi_error WifiLegacyHal::startGscan( 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 = [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(); if (status == WIFI_SUCCESS) { on_results_user_callback(id, cached_scan_results); return; } } // 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 = {onGscanFullResult, onGscanEvent}; wifi_error status = global_func_table_.wifi_start_gscan( id, wlan_interface_handle_, 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(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, wlan_interface_handle_); // 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::getValidFrequenciesForGscan(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( wlan_interface_handle_, 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::retrieveWlanInterfaceHandle() { const std::string& ifname_to_find = getStaIfaceName(); wifi_interface_handle* iface_handles = nullptr; Loading Loading @@ -245,12 +374,43 @@ void WifiLegacyHal::runEventLoop() { if_tool.SetWifiUpState(false); } std::pair<wifi_error, std::vector<wifi_cached_scan_results>> WifiLegacyHal::getGscanCachedResults() { 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( wlan_interface_handle_, 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(ERROR) << "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; wlan_interface_handle_ = nullptr; on_stop_complete_internal_callback = nullptr; 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; } } // namespace legacy_hal Loading wifi/1.0/default/wifi_legacy_hal.h +35 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,16 @@ struct PacketFilterCapabilities { uint32_t max_len; }; // 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>&)>; /** * Class that encapsulates all legacy HAL interactions. * This class manages the lifetime of the event loop thread used by legacy HAL. Loading @@ -65,12 +75,37 @@ class WifiLegacyHal { // APF functions. std::pair<wifi_error, PacketFilterCapabilities> getPacketFilterCapabilities(); wifi_error setPacketFilter(const std::vector<uint8_t>& program); // Gscan functions. std::pair<wifi_error, wifi_gscan_capabilities> getGscanCapabilities(); // 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( 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(wifi_request_id id); std::pair<wifi_error, std::vector<uint32_t>> getValidFrequenciesForGscan( wifi_band band); private: // Retrieve the interface handle to be used for the "wlan" interface. wifi_error retrieveWlanInterfaceHandle(); // 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(); void invalidate(); // Event loop thread used by legacy HAL. Loading Loading
wifi/1.0/default/wifi_legacy_hal.cpp +161 −1 Original line number Diff line number Diff line Loading @@ -28,8 +28,13 @@ namespace wifi { namespace V1_0 { namespace implementation { namespace legacy_hal { // Constants used in the class. // 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; // Legacy HAL functions accept "C" style function pointers, so use global // functions to pass to the legacy HAL function and store the corresponding Loading Loading @@ -57,6 +62,27 @@ void onFirmwareMemoryDump(char* buffer, int buffer_size) { 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 onGscanEvent(wifi_request_id id, wifi_scan_event event) { 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 onGscanFullResult(wifi_request_id id, wifi_scan_result* result, uint32_t buckets_scanned) { if (on_gscan_full_result_internal_callback) { on_gscan_full_result_internal_callback(id, result, buckets_scanned); } } // End of the free-standing "C" style callbacks. WifiLegacyHal::WifiLegacyHal() Loading Loading @@ -206,6 +232,109 @@ wifi_error WifiLegacyHal::setPacketFilter(const std::vector<uint8_t>& program) { wlan_interface_handle_, program.data(), program.size()); } std::pair<wifi_error, wifi_gscan_capabilities> WifiLegacyHal::getGscanCapabilities() { wifi_gscan_capabilities caps; wifi_error status = global_func_table_.wifi_get_gscan_capabilities( wlan_interface_handle_, &caps); return {status, caps}; } wifi_error WifiLegacyHal::startGscan( 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 = [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(); if (status == WIFI_SUCCESS) { on_results_user_callback(id, cached_scan_results); return; } } // 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 = {onGscanFullResult, onGscanEvent}; wifi_error status = global_func_table_.wifi_start_gscan( id, wlan_interface_handle_, 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(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, wlan_interface_handle_); // 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::getValidFrequenciesForGscan(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( wlan_interface_handle_, 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::retrieveWlanInterfaceHandle() { const std::string& ifname_to_find = getStaIfaceName(); wifi_interface_handle* iface_handles = nullptr; Loading Loading @@ -245,12 +374,43 @@ void WifiLegacyHal::runEventLoop() { if_tool.SetWifiUpState(false); } std::pair<wifi_error, std::vector<wifi_cached_scan_results>> WifiLegacyHal::getGscanCachedResults() { 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( wlan_interface_handle_, 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(ERROR) << "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; wlan_interface_handle_ = nullptr; on_stop_complete_internal_callback = nullptr; 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; } } // namespace legacy_hal Loading
wifi/1.0/default/wifi_legacy_hal.h +35 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,16 @@ struct PacketFilterCapabilities { uint32_t max_len; }; // 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>&)>; /** * Class that encapsulates all legacy HAL interactions. * This class manages the lifetime of the event loop thread used by legacy HAL. Loading @@ -65,12 +75,37 @@ class WifiLegacyHal { // APF functions. std::pair<wifi_error, PacketFilterCapabilities> getPacketFilterCapabilities(); wifi_error setPacketFilter(const std::vector<uint8_t>& program); // Gscan functions. std::pair<wifi_error, wifi_gscan_capabilities> getGscanCapabilities(); // 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( 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(wifi_request_id id); std::pair<wifi_error, std::vector<uint32_t>> getValidFrequenciesForGscan( wifi_band band); private: // Retrieve the interface handle to be used for the "wlan" interface. wifi_error retrieveWlanInterfaceHandle(); // 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(); void invalidate(); // Event loop thread used by legacy HAL. Loading