wifi: Add support for RSSI monitoring
Bug: 31991459
Test: Compiles
Change-Id: I8794cea12a0d1c727bd0e37123152c8da11eeabf
diff --git a/wifi/1.0/IWifiStaIface.hal b/wifi/1.0/IWifiStaIface.hal
index 41b2bad..7b514a7 100644
--- a/wifi/1.0/IWifiStaIface.hal
+++ b/wifi/1.0/IWifiStaIface.hal
@@ -45,9 +45,13 @@
*/
LINK_LAYER_STATS = 1 << 2,
/**
+ * If set indicates that the RSSI monitor APIs are supported.
+ */
+ RSSI_MONITOR = 1 << 3,
+ /**
* Tracks connection packets' fate.
*/
- DEBUG_PACKET_FATE_SUPPORTED = 1 << 3
+ DEBUG_PACKET_FATE_SUPPORTED = 1 << 4
};
/**
@@ -259,6 +263,44 @@
getLinkLayerStats() generates (WifiStatus status, StaLinkLayerStats stats);
/**
+ * Start RSSI monitoring on the currently connected access point.
+ * Once the monitoring is enabled,
+ * |IWifiStaIfaceEventCallback.onRssiThresholdBreached| callback must be
+ * invoked to indicate if the RSSI goes above |maxRssi| or below |minRssi|.
+ * Must fail if |StaIfaceCapabilityMask.RSSI_MONITOR| is not set.
+ *
+ * @param cmdId command Id to use for this invocation.
+ * @param maxRssi Maximum RSSI threshold.
+ * @param minRssi Minimum RSSI threshold.
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_ARGS_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+ * |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ startRssiMonitoring(CommandId cmdId, Rssi maxRssi, Rssi minRssi)
+ generates (WifiStatus status);
+
+ /**
+ * Stop RSSI monitoring.
+ * Must fail if |StaIfaceCapabilityMask.RSSI_MONITOR| is not set.
+ *
+ * @param cmdId command Id corresponding to the request.
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+ * |WifiStatusCode.ERROR_NOT_STARTED|,
+ * |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ */
+ stopRssiMonitoring(CommandId cmdId) generates (WifiStatus status);
+
+ /**
* API to start packet fate monitoring.
* - Once stared, monitoring must remain active until HAL is unloaded.
* - When HAL is unloaded, all packet fate buffers must be cleared.
diff --git a/wifi/1.0/IWifiStaIfaceEventCallback.hal b/wifi/1.0/IWifiStaIfaceEventCallback.hal
index d47d40c..e8df4c2 100644
--- a/wifi/1.0/IWifiStaIfaceEventCallback.hal
+++ b/wifi/1.0/IWifiStaIfaceEventCallback.hal
@@ -20,6 +20,8 @@
/**
* Callback indicating that an ongoing background scan request has failed.
* The background scan needs to be restarted to continue scanning.
+ *
+ * @param cmdId command ID corresponding to the request.
*/
oneway onBackgroundScanFailure(CommandId cmdId);
@@ -28,7 +30,7 @@
* |REPORT_EVENTS_FULL_RESULTS| flag set in
* |StaBackgroundScanBucketParameters.eventReportScheme|.
*
- * @param cmdId command Id corresponding to the request.
+ * @param cmdId command ID corresponding to the request.
* @parm result Full scan result for an AP.
*/
oneway onBackgroundFullScanResult(CommandId cmdId, StaScanResult result);
@@ -39,8 +41,18 @@
* |REPORT_EVENTS_EACH_SCAN| or one of the configured thresholds was
* breached.
*
- * @param cmdId command Id corresponding to the request.
+ * @param cmdId command ID corresponding to the request.
* @parm scanDatas List of scan result for all AP's seen since last callback.
*/
oneway onBackgroundScanResults(CommandId cmdId, vec<StaScanData> scanDatas);
+
+ /**
+ * Called when the RSSI of the currently connected access point goes beyond the
+ * thresholds set via |IWifiStaIface.startRssiMonitoring|.
+ *
+ * @param cmdId command ID corresponding to the request.
+ * @param currBssid BSSID of the currently connected access point.
+ * @param currRssi RSSI of the currently connected access point.
+ */
+ oneway onRssiThresholdBreached(CommandId cmdId, Bssid currBssid, Rssi currRssi);
};
diff --git a/wifi/1.0/default/hidl_struct_util.cpp b/wifi/1.0/default/hidl_struct_util.cpp
index e3e41c3..61a2c2c 100644
--- a/wifi/1.0/default/hidl_struct_util.cpp
+++ b/wifi/1.0/default/hidl_struct_util.cpp
@@ -64,6 +64,8 @@
return HidlStaIfaceCaps::BACKGROUND_SCAN;
case WIFI_FEATURE_LINK_LAYER_STATS:
return HidlStaIfaceCaps::LINK_LAYER_STATS;
+ case WIFI_FEATURE_RSSI_MONITOR:
+ return HidlStaIfaceCaps::RSSI_MONITOR;
};
CHECK(false) << "Unknown legacy feature: " << feature;
return {};
@@ -210,8 +212,9 @@
*hidl_caps |= convertLegacyLoggerFeatureToHidlStaIfaceCapability(feature);
}
}
- for (const auto feature :
- {WIFI_FEATURE_GSCAN, WIFI_FEATURE_LINK_LAYER_STATS}) {
+ for (const auto feature : {WIFI_FEATURE_GSCAN,
+ WIFI_FEATURE_LINK_LAYER_STATS,
+ WIFI_FEATURE_RSSI_MONITOR}) {
if (feature & legacy_feature_set) {
*hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature);
}
diff --git a/wifi/1.0/default/wifi_legacy_hal.cpp b/wifi/1.0/default/wifi_legacy_hal.cpp
index de1eb39..640a2f2 100644
--- a/wifi/1.0/default/wifi_legacy_hal.cpp
+++ b/wifi/1.0/default/wifi_legacy_hal.cpp
@@ -90,16 +90,25 @@
// 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 onLinkLayerStatsDataResult(wifi_request_id id,
- wifi_iface_stat* iface_stat,
- int num_radios,
- wifi_radio_stat* radio_stat) {
+void onLinkLayerStatsResult(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 onRssiThresholdBreached(wifi_request_id id, uint8_t* bssid, int8_t rssi) {
+ 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;
@@ -537,11 +546,53 @@
};
wifi_error status = global_func_table_.wifi_get_link_stats(
- 0, wlan_interface_handle_, {onLinkLayerStatsDataResult});
+ 0, wlan_interface_handle_, {onLinkLayerStatsResult});
on_link_layer_stats_result_internal_callback = nullptr;
return {status, link_stats};
}
+wifi_error WifiLegacyHal::startRssiMonitoring(
+ 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);
+ };
+ return global_func_table_.wifi_start_rssi_monitoring(
+ id,
+ wlan_interface_handle_,
+ max_rssi,
+ min_rssi,
+ {onRssiThresholdBreached});
+}
+
+wifi_error WifiLegacyHal::stopRssiMonitoring(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, wlan_interface_handle_);
+ // 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, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet() {
uint32_t supported_features;
wifi_error status = global_func_table_.wifi_get_logger_supported_feature_set(
@@ -1017,6 +1068,7 @@
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_rtt_results_internal_callback = nullptr;
on_nan_notify_response_user_callback = nullptr;
diff --git a/wifi/1.0/default/wifi_legacy_hal.h b/wifi/1.0/default/wifi_legacy_hal.h
index b569dbd..b68fa50 100644
--- a/wifi/1.0/default/wifi_legacy_hal.h
+++ b/wifi/1.0/default/wifi_legacy_hal.h
@@ -101,6 +101,10 @@
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
@@ -167,6 +171,13 @@
wifi_error enableLinkLayerStats(bool debug);
wifi_error disableLinkLayerStats();
std::pair<wifi_error, LinkLayerStats> getLinkLayerStats();
+ // RSSI monitor functions.
+ wifi_error startRssiMonitoring(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(wifi_request_id id);
// Logger/debug functions.
std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet();
wifi_error startPktFateMonitoring();
diff --git a/wifi/1.0/default/wifi_sta_iface.cpp b/wifi/1.0/default/wifi_sta_iface.cpp
index cc8edd1..c91a99b 100644
--- a/wifi/1.0/default/wifi_sta_iface.cpp
+++ b/wifi/1.0/default/wifi_sta_iface.cpp
@@ -163,6 +163,29 @@
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::startDebugPacketFateMonitoring(
startDebugPacketFateMonitoring_cb hidl_status_cb) {
return validateAndCall(this,
@@ -384,6 +407,35 @@
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()) {
+ callback->onRssiThresholdBreached(id, bssid, rssi);
+ }
+ };
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->startRssiMonitoring(
+ 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(cmd_id);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() {
legacy_hal::wifi_error legacy_status =
legacy_hal_.lock()->startPktFateMonitoring();
diff --git a/wifi/1.0/default/wifi_sta_iface.h b/wifi/1.0/default/wifi_sta_iface.h
index cdfe951..b4f2721 100644
--- a/wifi/1.0/default/wifi_sta_iface.h
+++ b/wifi/1.0/default/wifi_sta_iface.h
@@ -70,6 +70,13 @@
Return<void> disableLinkLayerStatsCollection(
disableLinkLayerStatsCollection_cb hidl_status_cb) override;
Return<void> getLinkLayerStats(getLinkLayerStats_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> startDebugPacketFateMonitoring(
startDebugPacketFateMonitoring_cb hidl_status_cb) override;
Return<void> stopDebugPacketFateMonitoring(
@@ -100,6 +107,10 @@
WifiStatus enableLinkLayerStatsCollectionInternal(bool debug);
WifiStatus disableLinkLayerStatsCollectionInternal();
std::pair<WifiStatus, StaLinkLayerStats> getLinkLayerStatsInternal();
+ WifiStatus startRssiMonitoringInternal(uint32_t cmd_id,
+ int32_t max_rssi,
+ int32_t min_rssi);
+ WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id);
WifiStatus startDebugPacketFateMonitoringInternal();
WifiStatus stopDebugPacketFateMonitoringInternal();
std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>