Wifi: Handle subsystem restart notification
This commit adds the logic to handle a notification of a wifi subsystem
restart to trigger the callback to the framework for self recovery.
Bug: 159367026
Test: force a firmware restart and make sure Wifi is recovered.
Change-Id: If6b5863d1d7473917088ec5be1910fa0db5dd6ae
diff --git a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
index 323d2ff..3f1af2e 100644
--- a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
@@ -263,6 +263,8 @@
return success;
}
+ static void subsystemRestartHandler(const std::string& /*error*/) {}
+
sp<WifiChip> chip_;
ChipId chip_id_ = kFakeChipId;
std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
@@ -278,8 +280,9 @@
public:
void SetUp() override {
- chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_,
- iface_util_, feature_flags_);
+ chip_ =
+ new WifiChip(chip_id_, legacy_hal_, mode_controller_, iface_util_,
+ feature_flags_, subsystemRestartHandler);
EXPECT_CALL(*mode_controller_, changeFirmwareMode(testing::_))
.WillRepeatedly(testing::Return(true));
diff --git a/wifi/1.4/default/wifi.cpp b/wifi/1.4/default/wifi.cpp
index 9c6b0f0..cfebfe0 100644
--- a/wifi/1.4/default/wifi.cpp
+++ b/wifi/1.4/default/wifi.cpp
@@ -107,9 +107,23 @@
}
WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
if (wifi_status.code == WifiStatusCode::SUCCESS) {
+ // Register the callback for subsystem restart
+ const auto& on_subsystem_restart_callback =
+ [this](const std::string& error) {
+ WifiStatus wifi_status =
+ createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error);
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onFailure(wifi_status).isOk()) {
+ LOG(ERROR) << "Failed to invoke onFailure callback";
+ }
+ }
+ };
+
// Create the chip instance once the HAL is started.
- chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,
- iface_util_, feature_flags_);
+ // Need to consider the case of multiple chips TODO(156998862)
+ chip_ =
+ new WifiChip(kChipId, legacy_hal_, mode_controller_, iface_util_,
+ feature_flags_, on_subsystem_restart_callback);
run_state_ = RunState::STARTED;
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onStart().isOk()) {
diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.4/default/wifi_chip.cpp
index 8747e61..96b83ac 100644
--- a/wifi/1.4/default/wifi_chip.cpp
+++ b/wifi/1.4/default/wifi_chip.cpp
@@ -335,7 +335,8 @@
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)
+ const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
+ const std::function<void(const std::string&)>& handler)
: chip_id_(chip_id),
legacy_hal_(legacy_hal),
mode_controller_(mode_controller),
@@ -343,7 +344,8 @@
is_valid_(true),
current_mode_id_(feature_flags::chip_mode_ids::kInvalid),
modes_(feature_flags.lock()->getChipModes()),
- debug_ring_buffer_cb_registered_(false) {
+ debug_ring_buffer_cb_registered_(false),
+ subsystemCallbackHandler_(handler) {
setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue);
}
@@ -737,6 +739,10 @@
current_mode_id_ = mode_id;
LOG(INFO) << "Configured chip in mode " << mode_id;
setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
+
+ legacy_hal_.lock()->registerSubsystemRestartCallbackHandler(
+ subsystemCallbackHandler_);
+
return status;
}
diff --git a/wifi/1.4/default/wifi_chip.h b/wifi/1.4/default/wifi_chip.h
index 98e18bb..e7650bd 100644
--- a/wifi/1.4/default/wifi_chip.h
+++ b/wifi/1.4/default/wifi_chip.h
@@ -50,13 +50,14 @@
*/
class WifiChip : public V1_4::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);
+ 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,
+ const std::function<void(const std::string&)>&
+ subsystemCallbackHandler);
// 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
@@ -282,6 +283,8 @@
hidl_callback_util::HidlCallbackHandler<IWifiChipEventCallback>
event_cb_handler_;
+ const std::function<void(const std::string&)> subsystemCallbackHandler_;
+
DISALLOW_COPY_AND_ASSIGN(WifiChip);
};
diff --git a/wifi/1.4/default/wifi_legacy_hal.cpp b/wifi/1.4/default/wifi_legacy_hal.cpp
index 29123bf..e9c3a0e 100644
--- a/wifi/1.4/default/wifi_legacy_hal.cpp
+++ b/wifi/1.4/default/wifi_legacy_hal.cpp
@@ -162,6 +162,15 @@
}
}
+// Callback to be invoked to report subsystem restart
+std::function<void(const char*)> on_subsystem_restart_internal_callback;
+void onAsyncSubsystemRestart(const char* error) {
+ const auto lock = hidl_sync_util::acquireGlobalLock();
+ if (on_subsystem_restart_internal_callback) {
+ on_subsystem_restart_internal_callback(error);
+ }
+}
+
// Callback to be invoked for rtt results results.
std::function<void(wifi_request_id, unsigned num_results,
wifi_rtt_result* rtt_results[])>
@@ -1049,6 +1058,23 @@
return status;
}
+wifi_error WifiLegacyHal::registerSubsystemRestartCallbackHandler(
+ const on_subsystem_restart_callback& on_restart_callback) {
+ if (on_subsystem_restart_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ on_subsystem_restart_internal_callback =
+ [on_restart_callback](const char* error) {
+ on_restart_callback(error);
+ };
+ wifi_error status = global_func_table_.wifi_set_subsystem_restart_handler(
+ global_handle_, {onAsyncSubsystemRestart});
+ if (status != WIFI_SUCCESS) {
+ on_subsystem_restart_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,
@@ -1471,6 +1497,7 @@
on_ring_buffer_data_internal_callback = nullptr;
on_error_alert_internal_callback = nullptr;
on_radio_mode_change_internal_callback = nullptr;
+ on_subsystem_restart_internal_callback = nullptr;
on_rtt_results_internal_callback = nullptr;
on_nan_notify_response_user_callback = nullptr;
on_nan_event_publish_terminated_user_callback = nullptr;
diff --git a/wifi/1.4/default/wifi_legacy_hal.h b/wifi/1.4/default/wifi_legacy_hal.h
index 9964460..2d4c594 100644
--- a/wifi/1.4/default/wifi_legacy_hal.h
+++ b/wifi/1.4/default/wifi_legacy_hal.h
@@ -142,6 +142,9 @@
using on_error_alert_callback =
std::function<void(int32_t, const std::vector<uint8_t>&)>;
+// Callback for subsystem restart
+using on_subsystem_restart_callback = std::function<void(const std::string&)>;
+
// Struct for the mac info from the legacy HAL. This is a cleaner version
// of the |wifi_mac_info| & |wifi_iface_info|.
typedef struct {
@@ -277,6 +280,8 @@
const on_ring_buffer_data_callback& on_data_callback);
wifi_error deregisterRingBufferCallbackHandler(
const std::string& iface_name);
+ wifi_error registerSubsystemRestartCallbackHandler(
+ const on_subsystem_restart_callback& on_restart_callback);
std::pair<wifi_error, std::vector<wifi_ring_buffer_status>>
getRingBuffersStatus(const std::string& iface_name);
wifi_error startRingBufferLogging(const std::string& iface_name,
diff --git a/wifi/1.4/default/wifi_legacy_hal_stubs.cpp b/wifi/1.4/default/wifi_legacy_hal_stubs.cpp
index 153a685..64b058e 100644
--- a/wifi/1.4/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.4/default/wifi_legacy_hal_stubs.cpp
@@ -143,6 +143,7 @@
populateStubFor(&hal_fn->wifi_virtual_interface_delete);
populateStubFor(&hal_fn->wifi_map_dscp_access_category);
populateStubFor(&hal_fn->wifi_reset_dscp_mapping);
+ populateStubFor(&hal_fn->wifi_set_subsystem_restart_handler);
return true;
}
} // namespace legacy_hal