/* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "hci/acl_manager/classic_acl_connection.h" #include #include "hci/address.h" #include "hci/event_checkers.h" #include "os/metrics.h" using bluetooth::hci::Address; namespace bluetooth { namespace hci { namespace acl_manager { class AclConnectionTracker : public ConnectionManagementCallbacks { public: AclConnectionTracker( AclConnectionInterface* acl_connection_interface, const Address& address, uint16_t connection_handle) : acl_connection_interface_(acl_connection_interface), address_(address), connection_handle_(connection_handle) {} ~AclConnectionTracker() { // If callbacks were registered, they should have been delivered. log::assert_that( client_callbacks_ == nullptr || queued_callbacks_.empty(), "assert failed: client_callbacks_ == nullptr || queued_callbacks_.empty()"); } void RegisterCallbacks(ConnectionManagementCallbacks* callbacks, os::Handler* handler) { client_handler_ = handler; client_callbacks_ = callbacks; while (!queued_callbacks_.empty()) { auto iter = queued_callbacks_.begin(); handler->Post(std::move(*iter)); queued_callbacks_.erase(iter); } } #define SAVE_OR_CALL(f, ...) \ if (client_handler_ == nullptr) { \ queued_callbacks_.emplace_back( \ common::BindOnce(&ConnectionManagementCallbacks::f, common::Unretained(this), ##__VA_ARGS__)); \ } else { \ client_handler_->Post( \ common::BindOnce(&ConnectionManagementCallbacks::f, common::Unretained(client_callbacks_), ##__VA_ARGS__)); \ } void OnConnectionPacketTypeChanged(uint16_t packet_type) override { SAVE_OR_CALL(OnConnectionPacketTypeChanged, packet_type) } void OnAuthenticationComplete(hci::ErrorCode hci_status) override { SAVE_OR_CALL(OnAuthenticationComplete, hci_status) } void OnEncryptionChange(EncryptionEnabled enabled) override { SAVE_OR_CALL(OnEncryptionChange, enabled) } void OnChangeConnectionLinkKeyComplete() override { SAVE_OR_CALL(OnChangeConnectionLinkKeyComplete) } void OnReadClockOffsetComplete(uint16_t clock_offset) override { SAVE_OR_CALL(OnReadClockOffsetComplete, clock_offset) } void OnModeChange(ErrorCode status, Mode current_mode, uint16_t interval) override { SAVE_OR_CALL(OnModeChange, status, current_mode, interval) } void OnSniffSubrating( hci::ErrorCode hci_status, uint16_t maximum_transmit_latency, uint16_t maximum_receive_latency, uint16_t minimum_remote_timeout, uint16_t minimum_local_timeout) override { SAVE_OR_CALL( OnSniffSubrating, hci_status, maximum_transmit_latency, maximum_receive_latency, minimum_remote_timeout, minimum_local_timeout); } void OnQosSetupComplete(ServiceType service_type, uint32_t token_rate, uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation) override { SAVE_OR_CALL(OnQosSetupComplete, service_type, token_rate, peak_bandwidth, latency, delay_variation) } void OnFlowSpecificationComplete(FlowDirection flow_direction, ServiceType service_type, uint32_t token_rate, uint32_t token_bucket_size, uint32_t peak_bandwidth, uint32_t access_latency) override { SAVE_OR_CALL(OnFlowSpecificationComplete, flow_direction, service_type, token_rate, token_bucket_size, peak_bandwidth, access_latency) } void OnFlushOccurred() override { SAVE_OR_CALL(OnFlushOccurred) } void OnRoleDiscoveryComplete(Role current_role) override { SAVE_OR_CALL(OnRoleDiscoveryComplete, current_role) } void OnReadLinkPolicySettingsComplete(uint16_t link_policy_settings) override { SAVE_OR_CALL(OnReadLinkPolicySettingsComplete, link_policy_settings) } void OnReadAutomaticFlushTimeoutComplete(uint16_t flush_timeout) override { SAVE_OR_CALL(OnReadAutomaticFlushTimeoutComplete, flush_timeout) } void OnReadTransmitPowerLevelComplete(uint8_t transmit_power_level) override { bluetooth::os::LogMetricReadTxPowerLevelResult( address_, connection_handle_, static_cast(ErrorCode::SUCCESS), transmit_power_level); SAVE_OR_CALL(OnReadTransmitPowerLevelComplete, transmit_power_level) } void OnReadLinkSupervisionTimeoutComplete(uint16_t link_supervision_timeout) override { SAVE_OR_CALL(OnReadLinkSupervisionTimeoutComplete, link_supervision_timeout) } void OnReadFailedContactCounterComplete(uint16_t failed_contact_counter) override { bluetooth::os::LogMetricReadFailedContactCounterResult( address_, connection_handle_, static_cast(ErrorCode::SUCCESS), failed_contact_counter); SAVE_OR_CALL(OnReadFailedContactCounterComplete, failed_contact_counter); } void OnReadLinkQualityComplete(uint8_t link_quality) override { SAVE_OR_CALL(OnReadLinkQualityComplete, link_quality) } void OnReadAfhChannelMapComplete(AfhMode afh_mode, std::array afh_channel_map) override { SAVE_OR_CALL(OnReadAfhChannelMapComplete, afh_mode, afh_channel_map) } void OnReadRssiComplete(uint8_t rssi) override { bluetooth::os::LogMetricReadRssiResult( address_, connection_handle_, static_cast(ErrorCode::SUCCESS), rssi); SAVE_OR_CALL(OnReadRssiComplete, rssi); } void OnReadClockComplete(uint32_t clock, uint16_t accuracy) override { SAVE_OR_CALL(OnReadClockComplete, clock, accuracy) } void OnCentralLinkKeyComplete(KeyFlag key_flag) override { SAVE_OR_CALL(OnCentralLinkKeyComplete, key_flag) } void OnRoleChange(hci::ErrorCode hci_status, Role new_role) override { SAVE_OR_CALL(OnRoleChange, hci_status, new_role) } void OnReadRemoteVersionInformationComplete( hci::ErrorCode hci_status, uint8_t lmp_version, uint16_t manufacturer_name, uint16_t sub_version) override { bluetooth::os::LogMetricRemoteVersionInfo( connection_handle_, static_cast(hci_status), lmp_version, manufacturer_name, sub_version); SAVE_OR_CALL(OnReadRemoteVersionInformationComplete, hci_status, lmp_version, manufacturer_name, sub_version); } void OnReadRemoteSupportedFeaturesComplete(uint64_t features) override { SAVE_OR_CALL(OnReadRemoteSupportedFeaturesComplete, features); } void OnReadRemoteExtendedFeaturesComplete(uint8_t page_number, uint8_t max_page_number, uint64_t features) override { SAVE_OR_CALL(OnReadRemoteExtendedFeaturesComplete, page_number, max_page_number, features); } void OnDisconnection(ErrorCode reason) { SAVE_OR_CALL(OnDisconnection, reason); } #undef SAVE_OR_CALL void on_role_discovery_complete(CommandCompleteView view) { auto complete_view = RoleDiscoveryCompleteView::Create(view); if (!complete_view.IsValid()) { log::error("Received on_role_discovery_complete with invalid packet"); return; } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { auto status = complete_view.GetStatus(); std::string error_code = ErrorCodeText(status); log::error("Received on_role_discovery_complete with error code {}", error_code); return; } OnRoleDiscoveryComplete(complete_view.GetCurrentRole()); } void on_read_link_policy_settings_complete(CommandCompleteView view) { auto complete_view = ReadLinkPolicySettingsCompleteView::Create(view); if (!complete_view.IsValid()) { log::error("Received on_read_link_policy_settings_complete with invalid packet"); return; } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { auto status = complete_view.GetStatus(); std::string error_code = ErrorCodeText(status); log::error("Received on_read_link_policy_settings_complete with error code {}", error_code); return; } OnReadLinkPolicySettingsComplete(complete_view.GetLinkPolicySettings()); } void on_read_automatic_flush_timeout_complete(CommandCompleteView view) { auto complete_view = ReadAutomaticFlushTimeoutCompleteView::Create(view); if (!complete_view.IsValid()) { log::error("Received on_read_automatic_flush_timeout_complete with invalid packet"); return; } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { auto status = complete_view.GetStatus(); std::string error_code = ErrorCodeText(status); log::error( "Received on_read_automatic_flush_timeout_complete with error code {}", error_code); return; } OnReadAutomaticFlushTimeoutComplete(complete_view.GetFlushTimeout()); } void on_read_transmit_power_level_complete(CommandCompleteView view) { auto complete_view = ReadTransmitPowerLevelCompleteView::Create(view); if (!complete_view.IsValid()) { log::error("Received on_read_transmit_power_level_complete with invalid packet"); return; } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { auto status = complete_view.GetStatus(); std::string error_code = ErrorCodeText(status); log::error("Received on_read_transmit_power_level_complete with error code {}", error_code); return; } OnReadTransmitPowerLevelComplete(complete_view.GetTransmitPowerLevel()); } void on_read_link_supervision_timeout_complete(CommandCompleteView view) { auto complete_view = ReadLinkSupervisionTimeoutCompleteView::Create(view); if (!complete_view.IsValid()) { log::error("Received on_read_link_supervision_timeout_complete with invalid packet"); return; } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { auto status = complete_view.GetStatus(); std::string error_code = ErrorCodeText(status); log::error( "Received on_read_link_supervision_timeout_complete with error code {}", error_code); return; } OnReadLinkSupervisionTimeoutComplete(complete_view.GetLinkSupervisionTimeout()); } void on_read_failed_contact_counter_complete(CommandCompleteView view) { auto complete_view = ReadFailedContactCounterCompleteView::Create(view); if (!complete_view.IsValid()) { log::error("Received on_read_failed_contact_counter_complete with invalid packet"); return; } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { auto status = complete_view.GetStatus(); std::string error_code = ErrorCodeText(status); log::error("Received on_read_failed_contact_counter_complete with error code {}", error_code); return; } OnReadFailedContactCounterComplete(complete_view.GetFailedContactCounter()); } void on_read_link_quality_complete(CommandCompleteView view) { auto complete_view = ReadLinkQualityCompleteView::Create(view); if (!complete_view.IsValid()) { log::error("Received on_read_link_quality_complete with invalid packet"); return; } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { auto status = complete_view.GetStatus(); std::string error_code = ErrorCodeText(status); log::error("Received on_read_link_quality_complete with error code {}", error_code); return; } OnReadLinkQualityComplete(complete_view.GetLinkQuality()); } void on_read_afh_channel_map_complete(CommandCompleteView view) { auto complete_view = ReadAfhChannelMapCompleteView::Create(view); if (!complete_view.IsValid()) { log::error("Received on_read_afh_channel_map_complete with invalid packet"); return; } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { auto status = complete_view.GetStatus(); std::string error_code = ErrorCodeText(status); log::error("Received on_read_afh_channel_map_complete with error code {}", error_code); return; } OnReadAfhChannelMapComplete(complete_view.GetAfhMode(), complete_view.GetAfhChannelMap()); } void on_read_rssi_complete(CommandCompleteView view) { auto complete_view = ReadRssiCompleteView::Create(view); if (!complete_view.IsValid()) { log::error("Received on_read_rssi_complete with invalid packet"); return; } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { auto status = complete_view.GetStatus(); std::string error_code = ErrorCodeText(status); log::error("Received on_read_rssi_complete with error code {}", error_code); return; } OnReadRssiComplete(complete_view.GetRssi()); } void on_read_remote_version_information_status(CommandStatusView view) { log::assert_that(view.IsValid(), "Bad status packet!"); } void on_read_remote_supported_features_status(CommandStatusView view) { log::assert_that(view.IsValid(), "Bad status packet!"); } void on_read_remote_extended_features_status(CommandStatusView view) { log::assert_that(view.IsValid(), "Bad status packet!"); } void on_read_clock_complete(CommandCompleteView view) { auto complete_view = ReadClockCompleteView::Create(view); if (!complete_view.IsValid()) { log::error("Received on_read_clock_complete with invalid packet"); return; } else if (complete_view.GetStatus() != ErrorCode::SUCCESS) { auto status = complete_view.GetStatus(); std::string error_code = ErrorCodeText(status); log::error("Received on_read_clock_complete with error code {}", error_code); return; } uint32_t clock = complete_view.GetClock(); uint16_t accuracy = complete_view.GetAccuracy(); OnReadClockComplete(clock, accuracy); } AclConnectionInterface* acl_connection_interface_; os::Handler* client_handler_ = nullptr; ConnectionManagementCallbacks* client_callbacks_ = nullptr; std::list queued_callbacks_; Address address_; uint16_t connection_handle_; }; struct ClassicAclConnection::impl { impl( AclConnectionInterface* acl_connection_interface, std::shared_ptr queue, const Address& address, uint16_t connection_handle) : tracker(acl_connection_interface, address, connection_handle), queue_(std::move(queue)) {} ConnectionManagementCallbacks* GetEventCallbacks(std::function invalidate_callbacks) { log::assert_that( !invalidate_callbacks_, "Already returned event callbacks for this connection"); invalidate_callbacks_ = std::move(invalidate_callbacks); return &tracker; } void PutEventCallbacks() { if (invalidate_callbacks_) invalidate_callbacks_(tracker.connection_handle_); invalidate_callbacks_ = {}; } AclConnectionTracker tracker; std::shared_ptr queue_; std::function invalidate_callbacks_; }; ClassicAclConnection::ClassicAclConnection() : AclConnection(), acl_connection_interface_(nullptr), address_(Address::kEmpty) {} ClassicAclConnection::ClassicAclConnection(std::shared_ptr queue, AclConnectionInterface* acl_connection_interface, uint16_t handle, Address address) : AclConnection(queue->GetUpEnd(), handle), acl_connection_interface_(acl_connection_interface), address_(address) { pimpl_ = new ClassicAclConnection::impl(acl_connection_interface, std::move(queue), address, handle); } ClassicAclConnection::~ClassicAclConnection() { if (pimpl_) pimpl_->PutEventCallbacks(); delete pimpl_; } ConnectionManagementCallbacks* ClassicAclConnection::GetEventCallbacks( std::function invalidate_callbacks) { return pimpl_->GetEventCallbacks(std::move(invalidate_callbacks)); } void ClassicAclConnection::RegisterCallbacks(ConnectionManagementCallbacks* callbacks, os::Handler* handler) { return pimpl_->tracker.RegisterCallbacks(callbacks, handler); } bool ClassicAclConnection::Disconnect(DisconnectReason reason) { acl_connection_interface_->EnqueueCommand( DisconnectBuilder::Create(handle_, reason), pimpl_->tracker.client_handler_->BindOnce(check_status)); return true; } bool ClassicAclConnection::ChangeConnectionPacketType(uint16_t packet_type) { acl_connection_interface_->EnqueueCommand( ChangeConnectionPacketTypeBuilder::Create(handle_, packet_type), pimpl_->tracker.client_handler_->BindOnce( check_status)); return true; } bool ClassicAclConnection::AuthenticationRequested() { acl_connection_interface_->EnqueueCommand( AuthenticationRequestedBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnce(check_status)); return true; } bool ClassicAclConnection::SetConnectionEncryption(Enable enable) { acl_connection_interface_->EnqueueCommand( SetConnectionEncryptionBuilder::Create(handle_, enable), pimpl_->tracker.client_handler_->BindOnce(check_status)); return true; } bool ClassicAclConnection::ChangeConnectionLinkKey() { acl_connection_interface_->EnqueueCommand( ChangeConnectionLinkKeyBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnce(check_status)); return true; } bool ClassicAclConnection::ReadClockOffset() { acl_connection_interface_->EnqueueCommand( ReadClockOffsetBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnce(check_status)); return true; } bool ClassicAclConnection::HoldMode(uint16_t max_interval, uint16_t min_interval) { acl_connection_interface_->EnqueueCommand( HoldModeBuilder::Create(handle_, max_interval, min_interval), pimpl_->tracker.client_handler_->BindOnce(check_status)); return true; } bool ClassicAclConnection::SniffMode(uint16_t max_interval, uint16_t min_interval, uint16_t attempt, uint16_t timeout) { acl_connection_interface_->EnqueueCommand( SniffModeBuilder::Create(handle_, max_interval, min_interval, attempt, timeout), pimpl_->tracker.client_handler_->BindOnce(check_status)); return true; } bool ClassicAclConnection::ExitSniffMode() { acl_connection_interface_->EnqueueCommand( ExitSniffModeBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnce(check_status)); return true; } bool ClassicAclConnection::QosSetup(ServiceType service_type, uint32_t token_rate, uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation) { acl_connection_interface_->EnqueueCommand( QosSetupBuilder::Create( handle_, service_type, token_rate, peak_bandwidth, latency, delay_variation), pimpl_->tracker.client_handler_->BindOnce(check_status)); return true; } bool ClassicAclConnection::RoleDiscovery() { acl_connection_interface_->EnqueueCommand( RoleDiscoveryBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_role_discovery_complete)); return true; } bool ClassicAclConnection::ReadLinkPolicySettings() { acl_connection_interface_->EnqueueCommand( ReadLinkPolicySettingsBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_link_policy_settings_complete)); return true; } bool ClassicAclConnection::WriteLinkPolicySettings(uint16_t link_policy_settings) { acl_connection_interface_->EnqueueCommand( WriteLinkPolicySettingsBuilder::Create(handle_, link_policy_settings), pimpl_->tracker.client_handler_->BindOnce( check_complete)); return true; } bool ClassicAclConnection::FlowSpecification(FlowDirection flow_direction, ServiceType service_type, uint32_t token_rate, uint32_t token_bucket_size, uint32_t peak_bandwidth, uint32_t access_latency) { acl_connection_interface_->EnqueueCommand( FlowSpecificationBuilder::Create( handle_, flow_direction, service_type, token_rate, token_bucket_size, peak_bandwidth, access_latency), pimpl_->tracker.client_handler_->BindOnce(check_status)); return true; } bool ClassicAclConnection::SniffSubrating(uint16_t maximum_latency, uint16_t minimum_remote_timeout, uint16_t minimum_local_timeout) { acl_connection_interface_->EnqueueCommand( SniffSubratingBuilder::Create( handle_, maximum_latency, minimum_remote_timeout, minimum_local_timeout), pimpl_->tracker.client_handler_->BindOnce(check_complete)); return true; } bool ClassicAclConnection::Flush() { acl_connection_interface_->EnqueueCommand( EnhancedFlushBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnce(check_status)); return true; } bool ClassicAclConnection::ReadAutomaticFlushTimeout() { acl_connection_interface_->EnqueueCommand( ReadAutomaticFlushTimeoutBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_automatic_flush_timeout_complete)); return true; } bool ClassicAclConnection::WriteAutomaticFlushTimeout(uint16_t flush_timeout) { acl_connection_interface_->EnqueueCommand( WriteAutomaticFlushTimeoutBuilder::Create(handle_, flush_timeout), pimpl_->tracker.client_handler_->BindOnce( check_complete)); return true; } bool ClassicAclConnection::ReadTransmitPowerLevel(TransmitPowerLevelType type) { acl_connection_interface_->EnqueueCommand( ReadTransmitPowerLevelBuilder::Create(handle_, type), pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_transmit_power_level_complete)); return true; } bool ClassicAclConnection::ReadLinkSupervisionTimeout() { acl_connection_interface_->EnqueueCommand( ReadLinkSupervisionTimeoutBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_link_supervision_timeout_complete)); return true; } bool ClassicAclConnection::WriteLinkSupervisionTimeout(uint16_t link_supervision_timeout) { acl_connection_interface_->EnqueueCommand( WriteLinkSupervisionTimeoutBuilder::Create(handle_, link_supervision_timeout), pimpl_->tracker.client_handler_->BindOnce( check_complete)); return true; } bool ClassicAclConnection::ReadFailedContactCounter() { acl_connection_interface_->EnqueueCommand( ReadFailedContactCounterBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_failed_contact_counter_complete)); return true; } bool ClassicAclConnection::ResetFailedContactCounter() { acl_connection_interface_->EnqueueCommand( ResetFailedContactCounterBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnce( check_complete)); return true; } bool ClassicAclConnection::ReadLinkQuality() { acl_connection_interface_->EnqueueCommand( ReadLinkQualityBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_link_quality_complete)); return true; } bool ClassicAclConnection::ReadAfhChannelMap() { acl_connection_interface_->EnqueueCommand( ReadAfhChannelMapBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_afh_channel_map_complete)); return true; } bool ClassicAclConnection::ReadRssi() { acl_connection_interface_->EnqueueCommand( ReadRssiBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_rssi_complete)); return true; } bool ClassicAclConnection::ReadRemoteVersionInformation() { acl_connection_interface_->EnqueueCommand( ReadRemoteVersionInformationBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_remote_version_information_status)); return true; } bool ClassicAclConnection::ReadRemoteSupportedFeatures() { acl_connection_interface_->EnqueueCommand( ReadRemoteSupportedFeaturesBuilder::Create(handle_), pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_remote_supported_features_status)); return true; } bool ClassicAclConnection::ReadRemoteExtendedFeatures(uint8_t page_number) { acl_connection_interface_->EnqueueCommand( ReadRemoteExtendedFeaturesBuilder::Create(handle_, page_number), pimpl_->tracker.client_handler_->BindOnceOn( &pimpl_->tracker, &AclConnectionTracker::on_read_remote_extended_features_status)); return true; } bool ClassicAclConnection::ReadClock(WhichClock which_clock) { pimpl_->tracker.acl_connection_interface_->EnqueueCommand( ReadClockBuilder::Create(handle_, which_clock), pimpl_->tracker.client_handler_->BindOnceOn(&pimpl_->tracker, &AclConnectionTracker::on_read_clock_complete)); return true; } } // namespace acl_manager } // namespace hci } // namespace bluetooth