Merge "CS: Implement Setup Phase" into main am: 731d32359b
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/2671047
Change-Id: Ibf32639f5434767bb220508f0ca7c46d5937264f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc
index 517edb7..554dbc7 100644
--- a/system/gd/hci/distance_measurement_manager.cc
+++ b/system/gd/hci/distance_measurement_manager.cc
@@ -35,6 +35,8 @@
static constexpr uint16_t kIllegalConnectionHandle = 0xffff;
static constexpr uint8_t kTxPowerNotAvailable = 0xfe;
static constexpr int8_t kRSSIDropOffAt1M = 41;
+static constexpr uint8_t kCsMaxTxPower = 12;
+static constexpr CsSyncAntennaSelection kCsSyncAntennaSelection = CsSyncAntennaSelection::ANTENNA_2;
struct DistanceMeasurementManager::impl {
~impl() {}
@@ -67,7 +69,7 @@
// Remove this check if we support any connection less method
if (connection_handle == kIllegalConnectionHandle) {
- LOG_WARN("Can not find any LE connection");
+ LOG_WARN("Can't find any LE connection for %s", ADDRESS_TO_LOGGABLE_CSTR(address));
distance_measurement_callbacks_->OnDistanceMeasurementStartFail(
address, REASON_NO_LE_CONNECTION, method);
return;
@@ -91,6 +93,35 @@
rssi_trackers[address].frequency = frequency;
}
} break;
+ case METHOD_CS: {
+ start_distance_measurement_with_cs(address, connection_handle);
+ } break;
+ }
+ }
+
+ void start_distance_measurement_with_cs(
+ const Address& cs_remote_address, uint16_t connection_handle) {
+ LOG_INFO(
+ "connection_handle: %d, address: %s",
+ connection_handle,
+ ADDRESS_TO_LOGGABLE_CSTR(cs_remote_address));
+ if (cs_trackers_.find(connection_handle) != cs_trackers_.end() &&
+ cs_trackers_[connection_handle].address != cs_remote_address) {
+ LOG_WARN("Remove old tracker for %s ", ADDRESS_TO_LOGGABLE_CSTR(cs_remote_address));
+ cs_trackers_.erase(connection_handle);
+ }
+
+ if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) {
+ // Create a cs tracker with role initiator
+ cs_trackers_[connection_handle].address = cs_remote_address;
+ // TODO: Check ROLE via CS config. (b/304295768)
+ cs_trackers_[connection_handle].role = CsRole::INITIATOR;
+ }
+
+ if (!cs_trackers_[connection_handle].setup_complete) {
+ send_le_cs_read_remote_supported_capabilities(connection_handle);
+ send_le_cs_set_default_settings(connection_handle);
+ send_le_cs_security_enable(connection_handle);
}
}
@@ -111,6 +142,14 @@
rssi_trackers.erase(address);
}
} break;
+ case METHOD_CS: {
+ uint16_t connection_handle = acl_manager_->HACK_GetLeHandle(address);
+ if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) {
+ LOG_WARN("Can't find CS tracker for %s ", ADDRESS_TO_LOGGABLE_CSTR(address));
+ } else {
+ cs_trackers_.erase(connection_handle);
+ }
+ } break;
}
}
@@ -142,22 +181,61 @@
}
void handle_event(LeMetaEventView event) {
+ if (!event.IsValid()) {
+ LOG_ERROR("Received invalid LeMetaEventView");
+ return;
+ }
switch (event.GetSubeventCode()) {
case hci::SubeventCode::LE_CS_TEST_END_COMPLETE:
case hci::SubeventCode::LE_CS_SUBEVENT_RESULT_CONTINUE:
case hci::SubeventCode::LE_CS_SUBEVENT_RESULT:
case hci::SubeventCode::LE_CS_PROCEDURE_ENABLE_COMPLETE:
case hci::SubeventCode::LE_CS_CONFIG_COMPLETE:
- case hci::SubeventCode::LE_CS_SECURITY_ENABLE_COMPLETE:
- case hci::SubeventCode::LE_CS_READ_REMOTE_FAE_TABLE_COMPLETE:
- case hci::SubeventCode::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE: {
+ case hci::SubeventCode::LE_CS_READ_REMOTE_FAE_TABLE_COMPLETE: {
LOG_WARN("Unhandled subevent %s", hci::SubeventCodeText(event.GetSubeventCode()).c_str());
} break;
+ case hci::SubeventCode::LE_CS_SECURITY_ENABLE_COMPLETE: {
+ on_cs_security_enable_complete(LeCsSecurityEnableCompleteView::Create(event));
+ } break;
+ case hci::SubeventCode::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE: {
+ on_cs_read_remote_supported_capabilities_complete(
+ LeCsReadRemoteSupportedCapabilitiesCompleteView::Create(event));
+ } break;
default:
LOG_INFO("Unknown subevent %s", hci::SubeventCodeText(event.GetSubeventCode()).c_str());
}
}
+ void send_le_cs_read_local_supported_capabilities() {
+ hci_layer_->EnqueueCommand(
+ LeCsReadLocalSupportedCapabilitiesBuilder::Create(),
+ handler_->BindOnceOn(this, &impl::on_cs_read_local_supported_capabilities));
+ }
+
+ void send_le_cs_read_remote_supported_capabilities(uint16_t connection_handle) {
+ hci_layer_->EnqueueCommand(
+ LeCsReadRemoteSupportedCapabilitiesBuilder::Create(connection_handle),
+ handler_->BindOnce(check_status<LeCsReadRemoteSupportedCapabilitiesStatusView>));
+ }
+
+ void send_le_cs_security_enable(uint16_t connection_handle) {
+ hci_layer_->EnqueueCommand(
+ LeCsSecurityEnableBuilder::Create(connection_handle),
+ handler_->BindOnce(check_status<LeCsSecurityEnableStatusView>));
+ }
+
+ void send_le_cs_set_default_settings(uint16_t connection_handle) {
+ uint8_t role_enable = ((uint8_t)CsRole::INITIATOR) | ((uint8_t)CsRole::INITIATOR);
+ hci_layer_->EnqueueCommand(
+ LeCsSetDefaultSettingsBuilder::Create(
+ connection_handle,
+ role_enable,
+ kCsSyncAntennaSelection,
+ kCsMaxTxPower // max_tx_power
+ ),
+ handler_->BindOnceOn(this, &impl::on_cs_set_default_settings_complete));
+ }
+
void on_cs_read_local_supported_capabilities(CommandCompleteView view) {
auto complete_view = LeCsReadLocalSupportedCapabilitiesCompleteView::Create(view);
if (!complete_view.IsValid()) {
@@ -176,6 +254,56 @@
cs_subfeature_supported_ = complete_view.GetOptionalSubfeaturesSupported();
}
+ void on_cs_read_remote_supported_capabilities_complete(
+ LeCsReadRemoteSupportedCapabilitiesCompleteView event_view) {
+ if (!event_view.IsValid()) {
+ LOG_INFO("Get invalid LeCsReadRemoteSupportedCapabilitiesCompleteView");
+ return;
+ }
+ uint16_t connection_handle = event_view.GetConnectionHandle();
+
+ if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) {
+ // Create a cs tracker with role reflector
+ // TODO: Check ROLE via CS config. (b/304295768)
+ cs_trackers_[connection_handle].role = CsRole::REFLECTOR;
+ send_le_cs_set_default_settings(event_view.GetConnectionHandle());
+ }
+
+ if (event_view.GetOptionalSubfeaturesSupported().phase_based_ranging_ == 0x01) {
+ cs_trackers_[connection_handle].remote_support_phase_based_ranging = true;
+ }
+ }
+
+ void on_cs_set_default_settings_complete(CommandCompleteView view) {
+ auto complete_view = LeCsSetDefaultSettingsCompleteView::Create(view);
+ if (!complete_view.IsValid()) {
+ LOG_WARN("Invalid LeCsSetDefaultSettingsComplete event");
+ return;
+ } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
+ std::string error_code = ErrorCodeText(complete_view.GetStatus());
+ LOG_WARN("Received LeCsSetDefaultSettingsComplete with error code %s", error_code.c_str());
+ return;
+ }
+ }
+
+ void on_cs_security_enable_complete(LeCsSecurityEnableCompleteView event_view) {
+ if (!event_view.IsValid()) {
+ LOG_INFO("get invalid LeCsSecurityEnableCompleteView");
+ return;
+ }
+
+ uint16_t connection_handle = event_view.GetConnectionHandle();
+ if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) {
+ LOG_WARN("Can't find cs tracker for connection_handle %d", connection_handle);
+ return;
+ }
+ cs_trackers_[connection_handle].setup_complete = true;
+ LOG_INFO(
+ "Setup phase complete, connection_handle: %d, address: %s",
+ connection_handle,
+ ADDRESS_TO_LOGGABLE_CSTR(cs_trackers_[connection_handle].address));
+ }
+
void on_read_remote_transmit_power_level_status(Address address, CommandStatusView view) {
auto status_view = LeReadRemoteTransmitPowerLevelStatusView::Create(view);
if (!status_view.IsValid()) {
@@ -307,12 +435,26 @@
std::unique_ptr<os::Alarm> alarm;
};
+ struct CsTracker {
+ Address address;
+ uint16_t local_counter;
+ uint16_t remote_counter;
+ CsRole role;
+ bool setup_complete = false;
+ bool config_set = false;
+ uint8_t main_mode_type;
+ uint8_t sub_mode_type;
+ CsRttType rtt_type;
+ bool remote_support_phase_based_ranging = false;
+ };
+
os::Handler* handler_;
hci::HciLayer* hci_layer_;
hci::AclManager* acl_manager_;
bool is_channel_sounding_supported_ = false;
hci::DistanceMeasurementInterface* distance_measurement_interface_;
std::unordered_map<Address, RSSITracker> rssi_trackers;
+ std::unordered_map<uint16_t, CsTracker> cs_trackers_;
DistanceMeasurementCallbacks* distance_measurement_callbacks_;
CsOptionalSubfeaturesSupported cs_subfeature_supported_;
};
diff --git a/system/gd/hci/distance_measurement_manager.h b/system/gd/hci/distance_measurement_manager.h
index a009bf3..2dd2a1b 100644
--- a/system/gd/hci/distance_measurement_manager.h
+++ b/system/gd/hci/distance_measurement_manager.h
@@ -24,6 +24,7 @@
enum DistanceMeasurementMethod {
METHOD_AUTO,
METHOD_RSSI,
+ METHOD_CS,
};
enum DistanceMeasurementErrorCode {