Root-Canal: Fix SCO / eSCO connection bringup

- Recognize HCI command Accept Connection Request for
  accepting SCO connections
- Correct usage of negative packet type bits

Bug: 209800014
Tag: #feature
Test: cert/run
Change-Id: If9703aa2ce2aca858040798ca9dc03badbbb3bfc
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc b/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
index 8da3f28..e70a8c8 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
+++ b/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
@@ -431,7 +431,7 @@
 }
 
 bool AclConnectionHandler::HasPendingScoConnection(bluetooth::hci::Address addr) const {
-  for (auto pair : sco_connections_) {
+  for (const auto& pair : sco_connections_) {
     if (std::get<ScoConnection>(pair).GetAddress() == addr) {
       ScoState state = std::get<ScoConnection>(pair).GetState();
       return state == SCO_STATE_PENDING ||
@@ -443,7 +443,7 @@
 }
 
 ScoState AclConnectionHandler::GetScoConnectionState(bluetooth::hci::Address addr) const {
-  for (auto pair : sco_connections_) {
+  for (const auto& pair : sco_connections_) {
     if (std::get<ScoConnection>(pair).GetAddress() == addr) {
       return std::get<ScoConnection>(pair).GetState();
     }
@@ -452,7 +452,7 @@
 }
 
 bool AclConnectionHandler::IsLegacyScoConnection(bluetooth::hci::Address addr) const {
-  for (auto pair : sco_connections_) {
+  for (const auto& pair : sco_connections_) {
     if (std::get<ScoConnection>(pair).GetAddress() == addr) {
       return std::get<ScoConnection>(pair).IsLegacy();
     }
@@ -471,8 +471,7 @@
 
 bool AclConnectionHandler::AcceptPendingScoConnection(bluetooth::hci::Address addr,
   ScoLinkParameters const &parameters) {
-
-  for (auto pair : sco_connections_) {
+  for (auto& pair : sco_connections_) {
     if (std::get<ScoConnection>(pair).GetAddress() == addr) {
       std::get<ScoConnection>(pair).SetLinkParameters(parameters);
       std::get<ScoConnection>(pair).SetState(ScoState::SCO_STATE_OPENED);
@@ -484,8 +483,7 @@
 
 bool AclConnectionHandler::AcceptPendingScoConnection(bluetooth::hci::Address addr,
   ScoConnectionParameters const &parameters) {
-
-  for (auto pair : sco_connections_) {
+  for (auto& pair : sco_connections_) {
     if (std::get<ScoConnection>(pair).GetAddress() == addr) {
       bool ok = std::get<ScoConnection>(pair).NegotiateLinkParameters(parameters);
       std::get<ScoConnection>(pair).SetState(
@@ -497,7 +495,7 @@
 }
 
 uint16_t AclConnectionHandler::GetScoHandle(bluetooth::hci::Address addr) const {
-  for (auto pair : sco_connections_) {
+  for (const auto& pair : sco_connections_) {
     if (std::get<ScoConnection>(pair).GetAddress() == addr) {
       return std::get<0>(pair);
     }
@@ -505,8 +503,18 @@
   return 0;
 }
 
+ScoConnectionParameters AclConnectionHandler::GetScoConnectionParameters(
+    bluetooth::hci::Address addr) const {
+  for (const auto& pair : sco_connections_) {
+    if (std::get<ScoConnection>(pair).GetAddress() == addr) {
+      return std::get<ScoConnection>(pair).GetConnectionParameters();
+    }
+  }
+  return {};
+}
+
 ScoLinkParameters AclConnectionHandler::GetScoLinkParameters(bluetooth::hci::Address addr) const {
-  for (auto pair : sco_connections_) {
+  for (const auto& pair : sco_connections_) {
     if (std::get<ScoConnection>(pair).GetAddress() == addr) {
       return std::get<ScoConnection>(pair).GetLinkParameters();
     }
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h b/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
index 58f8f50..0199609 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
+++ b/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
@@ -53,6 +53,8 @@
   bool AcceptPendingScoConnection(bluetooth::hci::Address addr,
     ScoConnectionParameters const &parameters);
   uint16_t GetScoHandle(bluetooth::hci::Address addr) const;
+  ScoConnectionParameters GetScoConnectionParameters(
+      bluetooth::hci::Address addr) const;
   ScoLinkParameters GetScoLinkParameters(bluetooth::hci::Address addr) const;
 
   bool CreatePendingLeConnection(bluetooth::hci::AddressWithType addr);
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc b/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
index b965428..f65219d 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
+++ b/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
@@ -1505,9 +1505,11 @@
           bluetooth::hci::LinkType::SCO,
           bluetooth::hci::Enable::DISABLED));
     } else {
+      ScoConnectionParameters connection_parameters =
+          connections_.GetScoConnectionParameters(address);
       send_event_(bluetooth::hci::SynchronousConnectionCompleteBuilder::Create(
           status, 0, address,
-          response.GetExtended() ?
+          connection_parameters.IsExtended() ?
             bluetooth::hci::ScoLinkType::ESCO :
             bluetooth::hci::ScoLinkType::SCO,
           0, 0, 0, 0, bluetooth::hci::ScoAirMode::TRANSPARENT));
@@ -2571,20 +2573,59 @@
   return ErrorCode::SUCCESS;
 }
 
-ErrorCode LinkLayerController::AcceptConnectionRequest(const Address& addr,
+ErrorCode LinkLayerController::AcceptConnectionRequest(const Address& bd_addr,
                                                        bool try_role_switch) {
-  if (!connections_.HasPendingConnection(addr)) {
-    LOG_INFO("No pending connection for %s", addr.ToString().c_str());
-    return ErrorCode::UNKNOWN_CONNECTION;
+  if (connections_.HasPendingConnection(bd_addr)) {
+    LOG_INFO("Accepting connection request from %s",
+             bd_addr.ToString().c_str());
+    ScheduleTask(kLongDelayMs, [this, bd_addr, try_role_switch]() {
+      LOG_INFO("Accepted connection from %s", bd_addr.ToString().c_str());
+      MakePeripheralConnection(bd_addr, try_role_switch);
+    });
+
+    return ErrorCode::SUCCESS;
   }
 
-  LOG_INFO("Accept in 200ms");
-  ScheduleTask(kLongDelayMs, [this, addr, try_role_switch]() {
-    LOG_INFO("Accepted");
-    MakePeripheralConnection(addr, try_role_switch);
-  });
+  // The HCI command Accept Connection may be used to accept incoming SCO
+  // connection requests.
+  if (connections_.HasPendingScoConnection(bd_addr)) {
+    ErrorCode status = ErrorCode::SUCCESS;
+    uint16_t sco_handle = 0;
+    ScoLinkParameters link_parameters = {};
+    ScoConnectionParameters connection_parameters =
+        connections_.GetScoConnectionParameters(bd_addr);
 
-  return ErrorCode::SUCCESS;
+    if (!connections_.AcceptPendingScoConnection(
+          bd_addr, connection_parameters)) {
+      connections_.CancelPendingScoConnection(bd_addr);
+      status = ErrorCode::SCO_INTERVAL_REJECTED;  // TODO: proper status code
+    } else {
+      sco_handle = connections_.GetScoHandle(bd_addr);
+      link_parameters = connections_.GetScoLinkParameters(bd_addr);
+    }
+
+    // Send eSCO connection response to peer.
+    SendLinkLayerPacket(model::packets::ScoConnectionResponseBuilder::Create(
+        properties_.GetAddress(), bd_addr, (uint8_t)status,
+        link_parameters.transmission_interval,
+        link_parameters.retransmission_window,
+        link_parameters.rx_packet_length,
+        link_parameters.tx_packet_length,
+        link_parameters.air_mode,
+        link_parameters.extended));
+
+    // Schedule HCI Connection Complete event.
+    ScheduleTask(kShortDelayMs, [this, status, sco_handle, bd_addr]() {
+      send_event_(bluetooth::hci::ConnectionCompleteBuilder::Create(
+          ErrorCode(status), sco_handle, bd_addr, bluetooth::hci::LinkType::SCO,
+          bluetooth::hci::Enable::DISABLED));
+    });
+
+    return ErrorCode::SUCCESS;
+  }
+
+  LOG_INFO("No pending connection for %s", bd_addr.ToString().c_str());
+  return ErrorCode::UNKNOWN_CONNECTION;
 }
 
 void LinkLayerController::MakePeripheralConnection(const Address& addr,
@@ -3658,9 +3699,14 @@
 
   // Save connection parameters.
   ScoConnectionParameters connection_parameters = {
-    8000, 8000, 0xffff, 0x60 /* 16bit CVSD */,
-    (uint8_t)bluetooth::hci::RetransmissionEffort::NO_RETRANSMISSION,
-    (uint16_t)((packet_type >> 5) & 0x7u)
+      8000, 8000, 0xffff, 0x60 /* 16bit CVSD */,
+      (uint8_t)bluetooth::hci::RetransmissionEffort::NO_RETRANSMISSION,
+      (uint16_t)(
+        (uint16_t)((packet_type >> 5) & 0x7u) |
+        (uint16_t)bluetooth::hci::SynchronousPacketTypeBits::NO_2_EV3_ALLOWED |
+        (uint16_t)bluetooth::hci::SynchronousPacketTypeBits::NO_3_EV3_ALLOWED |
+        (uint16_t)bluetooth::hci::SynchronousPacketTypeBits::NO_2_EV5_ALLOWED |
+        (uint16_t)bluetooth::hci::SynchronousPacketTypeBits::NO_3_EV5_ALLOWED)
   };
   connections_.CreateScoConnection(
       connections_.GetAddress(connection_handle).GetAddress(),
@@ -3746,7 +3792,7 @@
 
   if (!connections_.AcceptPendingScoConnection(bd_addr, connection_parameters)) {
     connections_.CancelPendingScoConnection(bd_addr);
-    status = ErrorCode::SCO_INTERVAL_REJECTED; // TODO: proper status code
+    status = ErrorCode::STATUS_UNKNOWN;  // TODO: proper status code
   } else {
     sco_handle = connections_.GetScoHandle(bd_addr);
     link_parameters = connections_.GetScoLinkParameters(bd_addr);
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/sco_connection.cc b/system/vendor_libs/test_vendor_lib/model/controller/sco_connection.cc
index 86efd71..6f577ef 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/sco_connection.cc
+++ b/system/vendor_libs/test_vendor_lib/model/controller/sco_connection.cc
@@ -29,7 +29,12 @@
     (uint16_t)SynchronousPacketTypeBits::HV1_ALLOWED |
     (uint16_t)SynchronousPacketTypeBits::HV2_ALLOWED |
     (uint16_t)SynchronousPacketTypeBits::HV3_ALLOWED;
-  return (packet_type & ~legacy) != 0;
+  uint16_t edr =
+    (uint16_t)SynchronousPacketTypeBits::NO_2_EV3_ALLOWED |
+    (uint16_t)SynchronousPacketTypeBits::NO_3_EV3_ALLOWED |
+    (uint16_t)SynchronousPacketTypeBits::NO_2_EV5_ALLOWED |
+    (uint16_t)SynchronousPacketTypeBits::NO_3_EV5_ALLOWED;
+  return ((packet_type ^ edr) & ~legacy) != 0;
 }
 
 std::optional<ScoLinkParameters> ScoConnectionParameters::GetLinkParameters() {
@@ -165,6 +170,7 @@
 
   if (retransmission_effort == (uint8_t)RetransmissionEffort::OPTIMIZED_FOR_POWER ||
       retransmission_effort == (uint8_t)RetransmissionEffort::OPTIMIZED_FOR_LINK_QUALITY) {
+    LOG_WARN("SCO Retransmission effort must be None or Don't care");
     return {};
   }
 
@@ -174,6 +180,7 @@
   uint8_t air_coding = voice_setting & 0x3;
 
   if (max_latency != 0xffff && max_latency < latency) {
+    LOG_WARN("SCO Max latency must be less than 1250 us");
     return {};
   }
 
@@ -183,10 +190,11 @@
   } else if (packet_type & (uint16_t)SynchronousPacketTypeBits::HV2_ALLOWED) {
     transmission_interval = 4;
     packet_length = 20;
-  } else if (packet_type & (uint16_t)SynchronousPacketTypeBits::HV3_ALLOWED) {
+  } else if (packet_type & (uint16_t)SynchronousPacketTypeBits::HV1_ALLOWED) {
     transmission_interval = 2;
     packet_length = 10;
   } else {
+    LOG_WARN("No SCO packet type enabled");
     return {};
   }
 
@@ -225,7 +233,7 @@
   uint16_t packet_type = (peer.packet_type & parameters_.packet_type) & 0x3f;
   packet_type |= (peer.packet_type | parameters_.packet_type) & 0x3c0;
 
-  if (packet_type == 0) {
+  if (packet_type == 0x3c0) {
     LOG_WARN("Packet type requirements cannot be met");
     LOG_WARN("Remote packet type: 0x%04x",
              static_cast<unsigned>(parameters_.packet_type));