wifi: Add support for alert handler

This is a debug mechanism provided for vendors to inform the framework
about the occurence of any fatal events.

Bug: 33620898
Test: Compiles
Change-Id: Ib6ac322131796792f66f87237a62eb8f5a013433
This commit is contained in:
Roshan Pius
2016-12-14 17:41:20 -08:00
parent 26801cb4ce
commit 203cb031df
7 changed files with 124 additions and 2 deletions

View File

@@ -163,6 +163,10 @@ interface IWifiChip {
* Host wake reasons stats collection.
*/
DEBUG_HOST_WAKE_REASON_STATS = 1 << 6,
/**
* Error alerts.
*/
DEBUG_ERROR_ALERTS = 1 << 7
};
/**
@@ -640,4 +644,21 @@ interface IWifiChip {
*/
getDebugHostWakeReasonStats()
generates (WifiStatus status, WifiDebugHostWakeReasonStats stats);
/**
* API to enable/disable alert notifications from the chip.
* These alerts must be used to notify framework of any fatal error events
* that the chip encounters via |IWifiChipEventCallback.onDebugErrorAlert| method.
* Must fail if |ChipCapabilityMask.DEBUG_ERROR_ALERTS| is not set.
*
* @param enable true to enable, false to disable.
* @return status WifiStatus of the operation.
* Possible status codes:
* |WifiStatusCode.SUCCESS|,
* |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
* |WifiStatusCode.ERROR_NOT_SUPPORTED|,
* |WifiStatusCode.NOT_AVAILABLE|,
* |WifiStatusCode.UNKNOWN|
*/
enableDebugErrorAlerts(bool enable) generates (WifiStatus status);
};

View File

@@ -70,4 +70,14 @@ interface IWifiChipEventCallback {
oneway onDebugRingBufferVendorDataEntriesAvailable(
WifiDebugRingBufferStatus status,
vec<WifiDebugRingEntryVendorData> entries);
/**
* Callback indicating that the chip has encountered a fatal error.
* Client must not attempt to parse either the errorCode or debugData.
* Must only be captured in a bugreport.
*
* @param errorCode Vendor defined error code.
* @param debugData Vendor defined data used for debugging.
*/
oneway onDebugErrorAlert(int32_t errorCode, vec<uint8_t> debugData);
};

View File

@@ -93,10 +93,11 @@ bool convertLegacyFeaturesToHidlChipCapabilities(
*hidl_caps |= convertLegacyLoggerFeatureToHidlChipCapability(feature);
}
}
// There is no flags for these 2 in the legacy feature set. Adding it to the
// set because all the current devices support it.
// 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_SUPPORTED;
*hidl_caps |= HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS;
*hidl_caps |= HidlChipCaps::DEBUG_ERROR_ALERTS;
return true;
}

View File

@@ -69,6 +69,10 @@ bool WifiChip::isValid() {
return is_valid_;
}
std::vector<sp<IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
return event_callbacks_;
}
Return<void> WifiChip::getId(getId_cb hidl_status_cb) {
return validateAndCall(this,
WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
@@ -319,6 +323,15 @@ Return<void> WifiChip::getDebugHostWakeReasonStats(
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);
}
void WifiChip::invalidateAndRemoveAllIfaces() {
invalidateAndClear(ap_iface_);
invalidateAndClear(nan_iface_);
@@ -706,6 +719,28 @@ WifiChip::getDebugHostWakeReasonStatsInternal() {
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()) {
callback->onDebugErrorAlert(error_code, debug_data);
}
};
legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
on_alert_callback);
} else {
legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler();
}
return createWifiStatusFromLegacyError(legacy_status);
}
} // namespace implementation
} // namespace V1_0
} // namespace wifi

View File

@@ -62,6 +62,7 @@ class WifiChip : public IWifiChip {
// valid before processing them.
void invalidate();
bool isValid();
std::vector<sp<IWifiChipEventCallback>> getEventCallbacks();
// HIDL methods exposed.
Return<void> getId(getId_cb hidl_status_cb) override;
@@ -119,6 +120,8 @@ class WifiChip : public IWifiChip {
forceDumpToDebugRingBuffer_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;
private:
void invalidateAndRemoveAllIfaces();
@@ -168,6 +171,7 @@ class WifiChip : public IWifiChip {
WifiStatus forceDumpToDebugRingBufferInternal(const hidl_string& ring_name);
std::pair<WifiStatus, WifiDebugHostWakeReasonStats>
getDebugHostWakeReasonStatsInternal();
WifiStatus enableDebugErrorAlertsInternal(bool enable);
ChipId chip_id_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;

View File

@@ -121,6 +121,18 @@ void onRingBufferData(char* ring_name,
}
}
// Callback to be invoked for error alert indication.
std::function<void(wifi_request_id, char*, int, int)>
on_error_alert_internal_callback;
void onErrorAlert(wifi_request_id id,
char* buffer,
int buffer_size,
int err_code) {
if (on_error_alert_internal_callback) {
on_error_alert_internal_callback(id, buffer, buffer_size, err_code);
}
}
// Callback to be invoked for rtt results results.
std::function<void(
wifi_request_id, unsigned num_results, wifi_rtt_result* rtt_results[])>
@@ -764,6 +776,38 @@ wifi_error WifiLegacyHal::getRingBufferData(const std::string& ring_name) {
ring_name_internal.data());
}
wifi_error WifiLegacyHal::registerErrorAlertCallbackHandler(
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, wlan_interface_handle_, {onErrorAlert});
if (status != WIFI_SUCCESS) {
on_error_alert_internal_callback = nullptr;
}
return status;
}
wifi_error WifiLegacyHal::deregisterErrorAlertCallbackHandler() {
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, wlan_interface_handle_);
}
wifi_error WifiLegacyHal::startRttRangeRequest(
wifi_request_id id,
const std::vector<wifi_rtt_config>& rtt_configs,
@@ -1114,6 +1158,7 @@ void WifiLegacyHal::invalidate() {
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_rtt_results_internal_callback = nullptr;
on_nan_notify_response_user_callback = nullptr;
on_nan_event_publish_terminated_user_callback = nullptr;

View File

@@ -118,6 +118,9 @@ using on_ring_buffer_data_callback =
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>&)>;
/**
* Class that encapsulates all legacy HAL interactions.
* This class manages the lifetime of the event loop thread used by legacy HAL.
@@ -196,6 +199,9 @@ class WifiLegacyHal {
uint32_t max_interval_sec,
uint32_t min_data_size);
wifi_error getRingBufferData(const std::string& ring_name);
wifi_error registerErrorAlertCallbackHandler(
const on_error_alert_callback& on_alert_callback);
wifi_error deregisterErrorAlertCallbackHandler();
// RTT functions.
wifi_error startRttRangeRequest(
wifi_request_id id,