OSDN Git Service

gd ACL: Print warnings for invalid handles
authorMyles Watson <mylesgw@google.com>
Thu, 3 Dec 2020 02:02:34 +0000 (18:02 -0800)
committerMyles Watson <mylesgw@google.com>
Thu, 3 Dec 2020 02:04:00 +0000 (18:04 -0800)
Bug: 174450658
Test: cert/run
Tag: #stability
Change-Id: Ibf9b856f74f20b48149a6db78dcac43194aae296

gd/hci/acl_manager.cc
gd/hci/acl_manager/classic_impl.h
gd/hci/acl_manager/le_impl.h

index 977cd6c..5b5f33b 100644 (file)
@@ -61,8 +61,10 @@ struct AclManager::impl {
     hci_queue_end_ = hci_layer_->GetAclQueueEnd();
     hci_queue_end_->RegisterDequeue(
         handler_, common::Bind(&impl::dequeue_and_route_acl_packet_to_connection, common::Unretained(this)));
-    classic_impl_ = new classic_impl(hci_layer_, controller_, handler_, round_robin_scheduler_);
-    le_impl_ = new le_impl(hci_layer_, controller_, handler_, round_robin_scheduler_);
+    bool crash_on_unknown_handle = false;
+    classic_impl_ =
+        new classic_impl(hci_layer_, controller_, handler_, round_robin_scheduler_, crash_on_unknown_handle);
+    le_impl_ = new le_impl(hci_layer_, controller_, handler_, round_robin_scheduler_, crash_on_unknown_handle);
   }
 
   void Stop() {
index 480bdd5..3177f23 100644 (file)
@@ -38,9 +38,16 @@ struct acl_connection {
 };
 
 struct classic_impl : public security::ISecurityManagerListener {
-  classic_impl(HciLayer* hci_layer, Controller* controller, os::Handler* handler,
-               RoundRobinScheduler* round_robin_scheduler)
-      : hci_layer_(hci_layer), controller_(controller), round_robin_scheduler_(round_robin_scheduler) {
+  classic_impl(
+      HciLayer* hci_layer,
+      Controller* controller,
+      os::Handler* handler,
+      RoundRobinScheduler* round_robin_scheduler,
+      bool crash_on_unknown_handle)
+      : hci_layer_(hci_layer),
+        controller_(controller),
+        round_robin_scheduler_(round_robin_scheduler),
+        crash_on_unknown_handle_(crash_on_unknown_handle) {
     hci_layer_ = hci_layer;
     controller_ = controller;
     handler_ = handler;
@@ -59,6 +66,15 @@ struct classic_impl : public security::ISecurityManagerListener {
     security_manager_.reset();
   }
 
+  ConnectionManagementCallbacks* get_callbacks(uint16_t handle) {
+    auto conn = acl_connections_.find(handle);
+    if (conn == acl_connections_.end()) {
+      return nullptr;
+    } else {
+      return conn->second.connection_management_callbacks_;
+    }
+  }
+
   void on_classic_event(EventPacketView event_packet) {
     EventCode event_code = event_packet.GetEventCode();
     switch (event_code) {
@@ -101,16 +117,19 @@ struct classic_impl : public security::ISecurityManagerListener {
       case EventCode::LINK_SUPERVISION_TIMEOUT_CHANGED:
         on_link_supervision_timeout_changed(event_packet);
         break;
+      case EventCode::CENTRAL_LINK_KEY_COMPLETE:
+        on_central_link_key_complete(event_packet);
+        break;
       default:
         LOG_ALWAYS_FATAL("Unhandled event code %s", EventCodeText(event_code).c_str());
     }
   }
 
   void on_classic_disconnect(uint16_t handle, ErrorCode reason) {
-    if (acl_connections_.count(handle) == 1) {
-      auto& connection = acl_connections_.find(handle)->second;
+    auto callbacks = get_callbacks(handle);
+    if (callbacks != nullptr) {
       round_robin_scheduler_->Unregister(handle);
-      connection.connection_management_callbacks_->OnDisconnection(reason);
+      callbacks->OnDisconnection(reason);
       acl_connections_.erase(handle);
     }
   }
@@ -122,11 +141,6 @@ struct classic_impl : public security::ISecurityManagerListener {
     client_handler_ = handler;
   }
 
-  void handle_disconnect(uint16_t handle, DisconnectReason reason) {
-    acl_connection_interface_->EnqueueCommand(hci::DisconnectBuilder::Create(handle, reason),
-                                              handler_->BindOnce(&check_command_status<DisconnectStatusView>));
-  }
-
   void on_incoming_connection(EventPacketView packet) {
     ConnectionRequestView request = ConnectionRequestView::Create(packet);
     ASSERT(request.IsValid());
@@ -206,16 +220,18 @@ struct classic_impl : public security::ISecurityManagerListener {
       return;
     }
     uint16_t handle = connection_complete.GetConnectionHandle();
-    ASSERT(acl_connections_.count(handle) == 0);
     auto queue = std::make_shared<AclConnection::Queue>(10);
-    acl_connections_.emplace(std::piecewise_construct, std::forward_as_tuple(handle),
-                             std::forward_as_tuple(AddressWithType{address, AddressType::PUBLIC_DEVICE_ADDRESS},
-                                                   queue->GetDownEnd(), handler_));
+    auto conn_pair = acl_connections_.emplace(
+        std::piecewise_construct,
+        std::forward_as_tuple(handle),
+        std::forward_as_tuple(
+            AddressWithType{address, AddressType::PUBLIC_DEVICE_ADDRESS}, queue->GetDownEnd(), handler_));
+    ASSERT(conn_pair.second);  // Make sure it's not a duplicate
     round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, queue);
     std::unique_ptr<ClassicAclConnection> connection(
         new ClassicAclConnection(std::move(queue), acl_connection_interface_, handle, address));
     connection->locally_initiated_ = locally_initiated;
-    auto& connection_proxy = check_and_get_connection(handle);
+    auto& connection_proxy = conn_pair.first->second;
     connection_proxy.connection_management_callbacks_ = connection->GetEventCallbacks();
     connection_proxy.connection_management_callbacks_->OnRoleChange(current_role);
     client_handler_->Post(common::BindOnce(&ConnectionCallbacks::OnConnectSuccess,
@@ -246,6 +262,13 @@ struct classic_impl : public security::ISecurityManagerListener {
       LOG_ERROR("Received on_connection_packet_type_changed with error code %s", error_code.c_str());
       return;
     }
+    uint16_t handle = packet_type_changed.GetConnectionHandle();
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
+    }
     // We don't handle this event; we didn't do this in legacy stack either.
   }
 
@@ -261,9 +284,14 @@ struct classic_impl : public security::ISecurityManagerListener {
       return;
     }
     uint16_t handle = complete_view.GetConnectionHandle();
-    auto& acl_connection = acl_connections_.find(handle)->second;
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
+    }
     KeyFlag key_flag = complete_view.GetKeyFlag();
-    acl_connection.connection_management_callbacks_->OnCentralLinkKeyComplete(key_flag);
+    callbacks->OnCentralLinkKeyComplete(key_flag);
   }
 
   void on_authentication_complete(EventPacketView packet) {
@@ -278,8 +306,13 @@ struct classic_impl : public security::ISecurityManagerListener {
       return;
     }
     uint16_t handle = authentication_complete.GetConnectionHandle();
-    auto& acl_connection = acl_connections_.find(handle)->second;
-    acl_connection.connection_management_callbacks_->OnAuthenticationComplete();
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
+    }
+    callbacks->OnAuthenticationComplete();
   }
 
   void cancel_connect(Address address) {
@@ -330,8 +363,13 @@ struct classic_impl : public security::ISecurityManagerListener {
       return;
     }
     uint16_t handle = complete_view.GetConnectionHandle();
-    auto& acl_connection = acl_connections_.find(handle)->second;
-    acl_connection.connection_management_callbacks_->OnChangeConnectionLinkKeyComplete();
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
+    }
+    callbacks->OnChangeConnectionLinkKeyComplete();
   }
 
   void on_read_clock_offset_complete(EventPacketView packet) {
@@ -346,9 +384,14 @@ struct classic_impl : public security::ISecurityManagerListener {
       return;
     }
     uint16_t handle = complete_view.GetConnectionHandle();
-    auto& acl_connection = acl_connections_.find(handle)->second;
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
+    }
     uint16_t clock_offset = complete_view.GetClockOffset();
-    acl_connection.connection_management_callbacks_->OnReadClockOffsetComplete(clock_offset);
+    callbacks->OnReadClockOffsetComplete(clock_offset);
   }
 
   void on_mode_change(EventPacketView packet) {
@@ -363,10 +406,15 @@ struct classic_impl : public security::ISecurityManagerListener {
       return;
     }
     uint16_t handle = mode_change_view.GetConnectionHandle();
-    auto& acl_connection = acl_connections_.find(handle)->second;
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
+    }
     Mode current_mode = mode_change_view.GetCurrentMode();
     uint16_t interval = mode_change_view.GetInterval();
-    acl_connection.connection_management_callbacks_->OnModeChange(current_mode, interval);
+    callbacks->OnModeChange(current_mode, interval);
   }
 
   void on_qos_setup_complete(EventPacketView packet) {
@@ -381,14 +429,18 @@ struct classic_impl : public security::ISecurityManagerListener {
       return;
     }
     uint16_t handle = complete_view.GetConnectionHandle();
-    auto& acl_connection = acl_connections_.find(handle)->second;
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
+    }
     ServiceType service_type = complete_view.GetServiceType();
     uint32_t token_rate = complete_view.GetTokenRate();
     uint32_t peak_bandwidth = complete_view.GetPeakBandwidth();
     uint32_t latency = complete_view.GetLatency();
     uint32_t delay_variation = complete_view.GetDelayVariation();
-    acl_connection.connection_management_callbacks_->OnQosSetupComplete(service_type, token_rate, peak_bandwidth,
-                                                                        latency, delay_variation);
+    callbacks->OnQosSetupComplete(service_type, token_rate, peak_bandwidth, latency, delay_variation);
   }
 
   void on_role_change(EventPacketView packet) {
@@ -423,14 +475,19 @@ struct classic_impl : public security::ISecurityManagerListener {
       return;
     }
     uint16_t handle = complete_view.GetConnectionHandle();
-    auto& acl_connection = acl_connections_.find(handle)->second;
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
+    }
     FlowDirection flow_direction = complete_view.GetFlowDirection();
     ServiceType service_type = complete_view.GetServiceType();
     uint32_t token_rate = complete_view.GetTokenRate();
     uint32_t token_bucket_size = complete_view.GetTokenBucketSize();
     uint32_t peak_bandwidth = complete_view.GetPeakBandwidth();
     uint32_t access_latency = complete_view.GetAccessLatency();
-    acl_connection.connection_management_callbacks_->OnFlowSpecificationComplete(
+    callbacks->OnFlowSpecificationComplete(
         flow_direction, service_type, token_rate, token_bucket_size, peak_bandwidth, access_latency);
   }
 
@@ -441,33 +498,50 @@ struct classic_impl : public security::ISecurityManagerListener {
       return;
     }
     uint16_t handle = flush_occurred_view.GetConnectionHandle();
-    auto& acl_connection = acl_connections_.find(handle)->second;
-    acl_connection.connection_management_callbacks_->OnFlushOccurred();
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
+    }
+    callbacks->OnFlushOccurred();
   }
 
   void on_read_remote_version_information(
       uint16_t handle, uint8_t version, uint16_t manufacturer_name, uint16_t sub_version) {
-    auto acl_connection = acl_connections_.find(handle);
-    if (acl_connection != acl_connections_.end()) {
-      acl_connection->second.connection_management_callbacks_->OnReadRemoteVersionInformationComplete(
-          version, manufacturer_name, sub_version);
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
     }
+    callbacks->OnReadRemoteVersionInformationComplete(version, manufacturer_name, sub_version);
   }
 
   void on_read_remote_supported_features_complete(EventPacketView packet) {
     auto view = ReadRemoteSupportedFeaturesCompleteView::Create(packet);
     ASSERT_LOG(view.IsValid(), "Read remote supported features packet invalid");
     uint16_t handle = view.GetConnectionHandle();
-    auto& acl_connection = acl_connections_.find(handle)->second;
-    acl_connection.connection_management_callbacks_->OnReadRemoteExtendedFeaturesComplete(0, 1, view.GetLmpFeatures());
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
+    }
+    callbacks->OnReadRemoteExtendedFeaturesComplete(0, 1, view.GetLmpFeatures());
   }
 
   void on_read_remote_extended_features_complete(EventPacketView packet) {
     auto view = ReadRemoteExtendedFeaturesCompleteView::Create(packet);
     ASSERT_LOG(view.IsValid(), "Read remote extended features packet invalid");
     uint16_t handle = view.GetConnectionHandle();
-    auto& acl_connection = acl_connections_.find(handle)->second;
-    acl_connection.connection_management_callbacks_->OnReadRemoteExtendedFeaturesComplete(
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
+    }
+    callbacks->OnReadRemoteExtendedFeaturesComplete(
         view.GetPageNumber(), view.GetMaximumPageNumber(), view.GetExtendedLmpFeatures());
   }
 
@@ -490,12 +564,6 @@ struct classic_impl : public security::ISecurityManagerListener {
         std::move(builder), handler_->BindOnce(&check_command_status<RejectConnectionRequestStatusView>));
   }
 
-  acl_connection& check_and_get_connection(uint16_t handle) {
-    auto connection = acl_connections_.find(handle);
-    ASSERT(connection != acl_connections_.end());
-    return connection->second;
-  }
-
   void OnDeviceBonded(bluetooth::hci::AddressWithType device) override {}
   void OnDeviceUnbonded(bluetooth::hci::AddressWithType device) override {}
   void OnDeviceBondFailed(bluetooth::hci::AddressWithType device, security::PairingFailure status) override {}
@@ -511,13 +579,14 @@ struct classic_impl : public security::ISecurityManagerListener {
       return;
     }
     uint16_t handle = encryption_change_view.GetConnectionHandle();
-    auto acl_connection = acl_connections_.find(handle);
-    if (acl_connection == acl_connections_.end()) {
-      LOG_INFO("Invalid handle (already closed?) %d", handle);
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Unknown connection handle 0x%04hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
       return;
     }
     EncryptionEnabled enabled = encryption_change_view.GetEncryptionEnabled();
-    acl_connection->second.connection_management_callbacks_->OnEncryptionChange(enabled);
+    callbacks->OnEncryptionChange(enabled);
   }
 
   void set_security_module(security::SecurityModule* security_module) {
@@ -548,6 +617,7 @@ struct classic_impl : public security::ISecurityManagerListener {
   std::queue<std::pair<Address, std::unique_ptr<CreateConnectionBuilder>>> pending_outgoing_connections_;
 
   std::unique_ptr<security::SecurityManager> security_manager_;
+  bool crash_on_unknown_handle_ = false;
 };
 
 }  // namespace acl_manager
index ec921cb..d430254 100644 (file)
@@ -43,8 +43,16 @@ struct le_acl_connection {
 };
 
 struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
-  le_impl(HciLayer* hci_layer, Controller* controller, os::Handler* handler, RoundRobinScheduler* round_robin_scheduler)
-      : hci_layer_(hci_layer), controller_(controller), round_robin_scheduler_(round_robin_scheduler) {
+  le_impl(
+      HciLayer* hci_layer,
+      Controller* controller,
+      os::Handler* handler,
+      RoundRobinScheduler* round_robin_scheduler,
+      bool crash_on_unknown_handle)
+      : hci_layer_(hci_layer),
+        controller_(controller),
+        round_robin_scheduler_(round_robin_scheduler),
+        crash_on_unknown_handle_(crash_on_unknown_handle) {
     hci_layer_ = hci_layer;
     controller_ = controller;
     handler_ = handler;
@@ -97,13 +105,22 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
     }
   }
 
+  LeConnectionManagementCallbacks* get_callbacks(uint16_t handle) {
+    auto connection = le_acl_connections_.find(handle);
+    if (connection == le_acl_connections_.end()) {
+      return nullptr;
+    }
+    return connection->second.le_connection_management_callbacks_;
+  }
+
   void on_le_disconnect(uint16_t handle, ErrorCode reason) {
-    if (le_acl_connections_.count(handle) == 1) {
-      auto& connection = le_acl_connections_.find(handle)->second;
-      round_robin_scheduler_->Unregister(handle);
-      connection.le_connection_management_callbacks_->OnDisconnection(reason);
-      le_acl_connections_.erase(handle);
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      return;
     }
+    round_robin_scheduler_->Unregister(handle);
+    callbacks->OnDisconnection(reason);
+    le_acl_connections_.erase(handle);
   }
 
   void on_common_le_connection_complete(AddressWithType address_with_type) {
@@ -151,11 +168,13 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
 
     auto role = connection_complete.GetRole();
     uint16_t handle = connection_complete.GetConnectionHandle();
-    ASSERT(le_acl_connections_.count(handle) == 0);
     auto queue = std::make_shared<AclConnection::Queue>(10);
-    le_acl_connections_.emplace(std::piecewise_construct, std::forward_as_tuple(handle),
-                                std::forward_as_tuple(remote_address, queue->GetDownEnd(), handler_));
-    auto& connection_proxy = check_and_get_le_connection(handle);
+    auto emplace_pair = le_acl_connections_.emplace(
+        std::piecewise_construct,
+        std::forward_as_tuple(handle),
+        std::forward_as_tuple(remote_address, queue->GetDownEnd(), handler_));
+    ASSERT(emplace_pair.second);  // Make sure the connection is unique
+    auto& connection_proxy = emplace_pair.first->second;
     round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, handle, queue);
     std::unique_ptr<LeAclConnection> connection(new LeAclConnection(
         std::move(queue), le_acl_connection_interface_, handle, local_address, remote_address, role));
@@ -211,11 +230,13 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
       return;
     }
     uint16_t handle = connection_complete.GetConnectionHandle();
-    ASSERT(le_acl_connections_.count(handle) == 0);
     auto queue = std::make_shared<AclConnection::Queue>(10);
-    le_acl_connections_.emplace(std::piecewise_construct, std::forward_as_tuple(handle),
-                                std::forward_as_tuple(remote_address, queue->GetDownEnd(), handler_));
-    auto& connection_proxy = check_and_get_le_connection(handle);
+    auto emplace_pair = le_acl_connections_.emplace(
+        std::piecewise_construct,
+        std::forward_as_tuple(handle),
+        std::forward_as_tuple(remote_address, queue->GetDownEnd(), handler_));
+    ASSERT(emplace_pair.second);  // Make sure it's not a duplicate
+    auto& connection_proxy = emplace_pair.first->second;
     round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, handle, queue);
     std::unique_ptr<LeAclConnection> connection(new LeAclConnection(
         std::move(queue), le_acl_connection_interface_, handle, local_address, remote_address, role));
@@ -237,22 +258,25 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
       return;
     }
     auto handle = complete_view.GetConnectionHandle();
-    if (le_acl_connections_.find(handle) == le_acl_connections_.end()) {
-      LOG_WARN("Can't find connection %hd", handle);
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Can't find connection 0x%hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
       return;
     }
-    auto& connection = le_acl_connections_.find(handle)->second;
-    connection.le_connection_management_callbacks_->OnConnectionUpdate(
+    callbacks->OnConnectionUpdate(
         complete_view.GetConnInterval(), complete_view.GetConnLatency(), complete_view.GetSupervisionTimeout());
   }
 
   void on_le_read_remote_version_information(
       uint16_t handle, uint8_t version, uint16_t manufacturer_name, uint16_t sub_version) {
-    auto connection = le_acl_connections_.find(handle);
-    if (connection != le_acl_connections_.end()) {
-      connection->second.le_connection_management_callbacks_->OnReadRemoteVersionInformationComplete(
-          version, manufacturer_name, sub_version);
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Can't find connection 0x%hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
     }
+    callbacks->OnReadRemoteVersionInformationComplete(version, manufacturer_name, sub_version);
   }
 
   void enqueue_command(std::unique_ptr<CommandPacketBuilder> command_packet) {
@@ -268,12 +292,13 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
       return;
     }
     auto handle = data_length_view.GetConnectionHandle();
-    auto connection_iterator = le_acl_connections_.find(handle);
-    if (connection_iterator == le_acl_connections_.end()) {
-      LOG_WARN("Can't find connection %hd", handle);
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Can't find connection 0x%hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
       return;
     }
-    connection_iterator->second.le_connection_management_callbacks_->OnDataLengthChange(
+    callbacks->OnDataLengthChange(
         data_length_view.GetMaxTxOctets(),
         data_length_view.GetMaxTxTime(),
         data_length_view.GetMaxRxOctets(),
@@ -287,11 +312,18 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
       return;
     }
 
+    auto handle = request_view.GetConnectionHandle();
+    auto callbacks = get_callbacks(handle);
+    if (callbacks == nullptr) {
+      LOG_WARN("Can't find connection 0x%hx", handle);
+      ASSERT(!crash_on_unknown_handle_);
+      return;
+    }
     // TODO: this is blindly accepting any parameters, just so we don't hang connection
     // have proper parameter negotiation
     le_acl_connection_interface_->EnqueueCommand(
         LeRemoteConnectionParameterRequestReplyBuilder::Create(
-            request_view.GetConnectionHandle(),
+            handle,
             request_view.GetIntervalMin(),
             request_view.GetIntervalMax(),
             request_view.GetLatency(),
@@ -498,12 +530,6 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
     le_client_handler_ = handler;
   }
 
-  le_acl_connection& check_and_get_le_connection(uint16_t handle) {
-    auto connection = le_acl_connections_.find(handle);
-    ASSERT(connection != le_acl_connections_.end());
-    return connection->second;
-  }
-
   bool check_connection_parameters(
       uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout) {
     if (conn_interval_min < 0x0006 || conn_interval_min > 0x0C80 || conn_interval_max < 0x0006 ||
@@ -594,6 +620,7 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback {
   bool address_manager_registered = false;
   bool ready_to_unregister = false;
   bool pause_connection = false;
+  bool crash_on_unknown_handle_ = false;
 };
 
 }  // namespace acl_manager