wifi(implementation): Make WifiLegacyHal.stop() blocking
IWifi::stop() is currently non-blocking which makes it hard for the
client to determing when the stop is fully complete. This for example
causes wificond to disable the wlan0 interface while the legacy HAL
stop is being processed. So, add a timed wait to let the legacy HAL
complete processing of the stop before we unblock the IWifi::stop()
HIDL call.
Bug: 64611487
Test: Manual tests by wifi state toggling and verifying the order of
events in logs:
08-15 19:17:53.302 796 796 I android.hardware.wifi@1.0-service:
Stopping legacy HAL
08-15 19:17:53.302 796 796 I WifiHAL : Sent msg on exit sock to
unblock poll()
08-15 19:17:53.302 796 4793 E CLD80211:
/vendor/bin/hw/android.hardware.wifi@1.0-service: Could not find group
host_logs, errno: 0 id: -2
08-15 19:17:53.302 796 4793 E CLD80211:
/vendor/bin/hw/android.hardware.wifi@1.0-service: Could not find group
fw_logs, errno: 0 id: -2
08-15 19:17:53.302 796 4793 E CLD80211:
/vendor/bin/hw/android.hardware.wifi@1.0-service: Could not find group
per_pkt_stats, errno: 0 id: -2
08-15 19:17:53.302 796 4793 E CLD80211:
/vendor/bin/hw/android.hardware.wifi@1.0-service: Could not find group
diag_events, errno: 0 id: -2
08-15 19:17:53.302 796 4793 E CLD80211:
/vendor/bin/hw/android.hardware.wifi@1.0-service: Could not find group
fatal_events, errno: 0 id: -2
08-15 19:17:53.302 796 4793 I CLD80211:
/vendor/bin/hw/android.hardware.wifi@1.0-service: Sent msg on exit sock
to unblock poll()
08-15 19:17:53.302 796 4793 I android.hardware.wifi@1.0-service:
Legacy HAL stop complete callback received
08-15 19:17:53.304 802 838 D CHRE : @ 151.328: [Platform] wifi:
has 0, enabled 0
08-15 19:17:53.321 796 4793 I android.hardware.wifi@1.0-service:
Legacy HAL event loop terminated
08-15 19:17:53.321 796 796 I android.hardware.wifi@1.0-service:
Legacy HAL stop complete
08-15 19:17:53.522 796 796 I android.hardware.wifi@1.0-service: Wifi
HAL stopped
Test: Will send for regression tests.
Change-Id: I394c11724e9459a4b9a6b970e2bcb4e0ad65fefc
diff --git a/wifi/1.1/default/wifi_legacy_hal.cpp b/wifi/1.1/default/wifi_legacy_hal.cpp
index 151a600..a6f6971 100644
--- a/wifi/1.1/default/wifi_legacy_hal.cpp
+++ b/wifi/1.1/default/wifi_legacy_hal.cpp
@@ -15,6 +15,7 @@
*/
#include <array>
+#include <chrono>
#include <android-base/logging.h>
#include <cutils/properties.h>
@@ -34,6 +35,7 @@
static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
static constexpr uint32_t kMaxRingBuffers = 10;
+static constexpr uint32_t kMaxStopCompleteWaitMs = 50;
// Helper function to create a non-const char* for legacy Hal API's.
std::vector<char> makeCharVec(const std::string& str) {
@@ -53,7 +55,8 @@
// 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.
+//
+// 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();
@@ -369,6 +372,7 @@
}
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";
@@ -376,19 +380,27 @@
return WIFI_SUCCESS;
}
LOG(DEBUG) << "Stopping legacy HAL";
- on_stop_complete_internal_callback = [on_stop_complete_user_callback,
- this](wifi_handle handle) {
+ 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_.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";
- is_started_ = false;
return WIFI_SUCCESS;
}
@@ -1257,11 +1269,13 @@
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>>