Merge "Use std::future to synchronize AclManagerTest"
diff --git a/gd/hci/controller.cc b/gd/hci/controller.cc
index 37a41e4..9d87ee3 100644
--- a/gd/hci/controller.cc
+++ b/gd/hci/controller.cc
@@ -590,7 +590,7 @@
       OP_CODE_MAPPING(LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH)
       OP_CODE_MAPPING(LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH)
       OP_CODE_MAPPING(LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND)
-      OP_CODE_MAPPING(LE_GENERATE_DHKEY_COMMAND)
+      OP_CODE_MAPPING(LE_GENERATE_DHKEY_COMMAND_V1)
       OP_CODE_MAPPING(LE_ADD_DEVICE_TO_RESOLVING_LIST)
       OP_CODE_MAPPING(LE_REMOVE_DEVICE_FROM_RESOLVING_LIST)
       OP_CODE_MAPPING(LE_CLEAR_RESOLVING_LIST)
@@ -631,6 +631,7 @@
       OP_CODE_MAPPING(LE_READ_RF_PATH_COMPENSATION_POWER)
       OP_CODE_MAPPING(LE_WRITE_RF_PATH_COMPENSATION_POWER)
       OP_CODE_MAPPING(LE_SET_PRIVACY_MODE)
+      OP_CODE_MAPPING(LE_GENERATE_DHKEY_COMMAND)
       // vendor specific
       case OpCode::LE_GET_VENDOR_CAPABILITIES:
         return vendor_capabilities_.is_supported_ == 0x01;
diff --git a/gd/hci/hci_packets.pdl b/gd/hci/hci_packets.pdl
index 19f41de..18838d4 100644
--- a/gd/hci/hci_packets.pdl
+++ b/gd/hci/hci_packets.pdl
@@ -263,7 +263,7 @@
   LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH = 0x2023,
   LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH = 0x2024,
   LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND = 0x2025,
-  LE_GENERATE_DHKEY_COMMAND = 0x2026,
+  LE_GENERATE_DHKEY_COMMAND_V1 = 0x2026,
   LE_ADD_DEVICE_TO_RESOLVING_LIST = 0x2027,
   LE_REMOVE_DEVICE_FROM_RESOLVING_LIST = 0x2028,
   LE_CLEAR_RESOLVING_LIST = 0x2029,
@@ -304,6 +304,7 @@
   LE_READ_RF_PATH_COMPENSATION_POWER = 0x204C,
   LE_WRITE_RF_PATH_COMPENSATION_POWER = 0x204D,
   LE_SET_PRIVACY_MODE = 0x204E,
+  LE_GENERATE_DHKEY_COMMAND = 0x205E,
 
   // VENDOR_SPECIFIC
   LE_GET_VENDOR_CAPABILITIES = 0xFD53,
@@ -493,7 +494,7 @@
   LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH = 337,
   LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH = 340,
   LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND = 341,
-  LE_GENERATE_DHKEY_COMMAND = 342,
+  LE_GENERATE_DHKEY_COMMAND_V1 = 342,
   LE_ADD_DEVICE_TO_RESOLVING_LIST = 343,
   LE_REMOVE_DEVICE_FROM_RESOLVING_LIST = 344,
   LE_CLEAR_RESOLVING_LIST = 345,
@@ -534,6 +535,7 @@
   LE_READ_RF_PATH_COMPENSATION_POWER = 390,
   LE_WRITE_RF_PATH_COMPENSATION_POWER = 391,
   LE_SET_PRIVACY_MODE = 392,
+  LE_GENERATE_DHKEY_COMMAND = 412,
 }
 
 packet CommandPacket {
@@ -1369,12 +1371,25 @@
   _reserved_ : 4,
 }
 
+enum PinType : 8 {
+  VARIABLE = 0,
+  FIXED = 1,
+}
+
 packet ReadPinType : CommandPacket (op_code = READ_PIN_TYPE) {
-  _payload_,  // placeholder (unimplemented)
+}
+
+packet ReadPinTypeComplete : CommandComplete (command_op_code = READ_PIN_TYPE) {
+  status : ErrorCode,
+  pin_type : PinType,
 }
 
 packet WritePinType : CommandPacket (op_code = WRITE_PIN_TYPE) {
-  _payload_,  // placeholder (unimplemented)
+  pin_type : PinType,
+}
+
+packet WritePinTypeComplete : CommandComplete (command_op_code = WRITE_PIN_TYPE) {
+  status : ErrorCode,
 }
 
 packet CreateNewUnitKey : CommandPacket (op_code = CREATE_NEW_UNIT_KEY) {
@@ -1444,11 +1459,19 @@
 }
 
 packet ReadConnectionAcceptTimeout : ConnectionManagementCommand (op_code = READ_CONNECTION_ACCEPT_TIMEOUT) {
-  _payload_,  // placeholder (unimplemented)
+}
+
+packet ReadConnectionAcceptTimeoutComplete : CommandComplete (command_op_code = READ_CONNECTION_ACCEPT_TIMEOUT) {
+  status : ErrorCode,
+  conn_accept_timeout : 16, // 0x0001 to 0xB540 (N * 0.625 ms) 0.625 ms to 29 s
 }
 
 packet WriteConnectionAcceptTimeout : ConnectionManagementCommand (op_code = WRITE_CONNECTION_ACCEPT_TIMEOUT) {
-  _payload_,  // placeholder (unimplemented)
+  conn_accept_timeout : 16, // 0x0001 to 0xB540 (N * 0.625 ms) 0.625 ms to 29 s, Default 0x1FA0, 5.06s
+}
+
+packet WriteConnectionAcceptTimeoutComplete : CommandComplete (command_op_code = WRITE_CONNECTION_ACCEPT_TIMEOUT) {
+  status : ErrorCode,
 }
 
 packet ReadPageTimeout : DiscoveryCommand (op_code = READ_PAGE_TIMEOUT) {
@@ -1724,7 +1747,11 @@
 }
 
 packet SetAfhHostChannelClassification : CommandPacket (op_code = SET_AFH_HOST_CHANNEL_CLASSIFICATION) {
-  _payload_,  // placeholder (unimplemented)
+  afh_host_channel_classification : 8[10],
+}
+
+packet SetAfhHostChannelClassificationComplete : CommandComplete (command_op_code = SET_AFH_HOST_CHANNEL_CLASSIFICATION) {
+  status : ErrorCode,
 }
 
 enum InquiryScanType : 8 {
@@ -2437,19 +2464,36 @@
 }
 
 packet LeSetHostChannelClassification : LeConnectionManagementCommand (op_code = LE_SET_HOST_CHANNEL_CLASSIFICATION) {
-  _payload_,  // placeholder (unimplemented)
+  channel_map : 8[5],
+}
+
+packet LeSetHostChannelClassificationComplete : CommandComplete (command_op_code = LE_SET_HOST_CHANNEL_CLASSIFICATION) {
+  status : ErrorCode,
 }
 
 packet LeReadChannelMap : LeConnectionManagementCommand (op_code = LE_READ_CHANNEL_MAP) {
-  _payload_,  // placeholder (unimplemented)
+}
+
+packet LeReadChannelMapComplete : CommandComplete (command_op_code = LE_SET_HOST_CHANNEL_CLASSIFICATION) {
+  status : ErrorCode,
+  connection_handle : 12,
+  _reserved_ : 4,
+  channel_map : 8[5],
 }
 
 packet LeReadRemoteFeatures : LeConnectionManagementCommand (op_code = LE_READ_REMOTE_FEATURES) {
-  _payload_,  // placeholder (unimplemented)
+  connection_handle : 12,
+  _reserved_ : 4,
 }
 
 packet LeEncrypt : LeSecurityCommand (op_code = LE_ENCRYPT) {
-  _payload_,  // placeholder (unimplemented)
+  key : 8[16],
+  plaintext_data : 8[16],
+}
+
+packet LeEncryptComplete : CommandComplete (command_op_code = LE_ENCRYPT) {
+  status : ErrorCode,
+  encrypted_data : 8[16],
 }
 
 packet LeRand : LeSecurityCommand (op_code = LE_RAND) {
@@ -2475,8 +2519,21 @@
   long_term_key: 8[16],
 }
 
+packet LeLongTermKeyRequestReplyComplete : CommandComplete (command_op_code = LE_LONG_TERM_KEY_REQUEST_REPLY) {
+  status : ErrorCode,
+  connection_handle : 12,
+  _reserved_ : 4,
+}
+
 packet LeLongTermKeyRequestNegativeReply : LeSecurityCommand (op_code = LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY) {
-  _payload_,  // placeholder (unimplemented)
+  connection_handle : 12,
+  _reserved_ : 4,
+}
+
+packet LeLongTermKeyRequestNegativeReplyComplete : CommandComplete (command_op_code = LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY) {
+  status : ErrorCode,
+  connection_handle : 12,
+  _reserved_ : 4,
 }
 
 packet LeReadSupportedStates : CommandPacket (op_code = LE_READ_SUPPORTED_STATES) {
@@ -2500,36 +2557,80 @@
 }
 
 packet LeRemoteConnectionParameterRequestReply : LeConnectionManagementCommand (op_code = LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY) {
-  _payload_,  // placeholder (unimplemented)
+  connection_handle : 12,
+  _reserved_ : 4,
+  interval_min : 16, // 0x0006-0x0C80 (7.5ms to 4s)
+  interval_max : 16, // 0x0006-0x0C80 (7.5ms to 4s)
+  latency : 16, // 0x0006-0x01F3
+  timeout : 16, // 0x00A to 0x0C80 (100ms to 32s)
+  minimum_ce_length : 16, // 0.625ms
+  maximum_ce_length : 16, // 0.625ms
+}
+
+packet LeRemoteConnectionParameterRequestReplyComplete : CommandComplete (command_op_code = LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY) {
+  status : ErrorCode,
+  connection_handle : 12,
+  _reserved_ : 4,
 }
 
 packet LeRemoteConnectionParameterRequestNegativeReply : LeConnectionManagementCommand (op_code = LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY) {
-  _payload_,  // placeholder (unimplemented)
+  connection_handle : 12,
+  _reserved_ : 4,
+  reason : ErrorCode,
 }
 
+packet LeRemoteConnectionParameterRequestNegativeReplyComplete : CommandComplete (command_op_code = LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY) {
+  status : ErrorCode,
+  connection_handle : 12,
+  _reserved_ : 4,
+}
 
 packet LeSetDataLength : LeConnectionManagementCommand (op_code = LE_SET_DATA_LENGTH) {
-  _payload_,  // placeholder (unimplemented)
+  connection_handle : 12,
+  _reserved_ : 4,
+  tx_octets : 16, // payload octets per single PDU 0x1B to 0x00FB
+  tx_time : 16, // microseconds used to transmit a single PDU 0x0148 to 0x4290
+}
+
+packet LeSetDataLengthComplete : CommandComplete (command_op_code = LE_SET_DATA_LENGTH) {
+  status : ErrorCode,
+  connection_handle : 12,
+  _reserved_ : 4,
 }
 
 packet LeReadSuggestedDefaultDataLength : LeConnectionManagementCommand (op_code = LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH) {
-  _payload_,  // placeholder (unimplemented)
+}
+
+packet LeReadSuggestedDefaultDataLengthComplete : CommandComplete (command_op_code = LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH) {
+  status : ErrorCode,
+  tx_octets : 16, // payload octets per single PDU 0x1B to 0x00FB
+  tx_time : 16, // microseconds used to transmit a single PDU 0x0148 to 0x4290
 }
 
 packet LeWriteSuggestedDefaultDataLength : LeConnectionManagementCommand (op_code = LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH) {
-  _payload_,  // placeholder (unimplemented)
+  tx_octets : 16, // payload octets per single PDU 0x1B to 0x00FB
+  tx_time : 16, // microseconds used to transmit a single PDU 0x0148 to 0x4290
+}
+
+packet LeWriteSuggestedDefaultDataLengthComplete : CommandComplete (command_op_code = LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH) {
+  status : ErrorCode,
 }
 
 packet LeReadLocalP256PublicKeyCommand : LeSecurityCommand (op_code = LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND) {
-  _payload_,  // placeholder (unimplemented)
 }
 
-packet LeGenerateDhkeyCommand : LeSecurityCommand (op_code = LE_GENERATE_DHKEY_COMMAND) {
-  _payload_,  // placeholder (unimplemented)
+packet LeGenerateDhkeyV1Command : LeSecurityCommand (op_code = LE_GENERATE_DHKEY_COMMAND_V1) {
+  remote_p_256_public_key : 8[64],
+}
+
+packet LeGenerateDhkeyV1CommandStatus : CommandStatus (command_op_code = LE_GENERATE_DHKEY_COMMAND_V1) {
 }
 
 packet LeAddDeviceToResolvingList : LeSecurityCommand (op_code = LE_ADD_DEVICE_TO_RESOLVING_LIST) {
-  _payload_,  // placeholder (unimplemented)
+  peer_identity_address_type : PeerAddressType,
+  peer_identity_address : Address,
+  peer_irk : 8[16],
+  local_irk : 8[16],
 }
 
 packet LeAddDeviceToResolvingListComplete : CommandComplete (command_op_code = LE_ADD_DEVICE_TO_RESOLVING_LIST) {
@@ -2537,7 +2638,8 @@
 }
 
 packet LeRemoveDeviceFromResolvingList : LeSecurityCommand (op_code = LE_REMOVE_DEVICE_FROM_RESOLVING_LIST) {
-  _payload_,  // placeholder (unimplemented)
+  peer_identity_address_type : PeerAddressType,
+  peer_identity_address : Address,
 }
 
 packet LeRemoveDeviceFromResolvingListComplete : CommandComplete (command_op_code = LE_REMOVE_DEVICE_FROM_RESOLVING_LIST) {
@@ -2545,7 +2647,6 @@
 }
 
 packet LeClearResolvingList : LeSecurityCommand (op_code = LE_CLEAR_RESOLVING_LIST) {
-  _payload_,  // placeholder (unimplemented)
 }
 
 packet LeClearResolvingListComplete : CommandComplete (command_op_code = LE_CLEAR_RESOLVING_LIST) {
@@ -2553,23 +2654,46 @@
 }
 
 packet LeReadResolvingListSize : LeSecurityCommand (op_code = LE_READ_RESOLVING_LIST_SIZE) {
-  _payload_,  // placeholder (unimplemented)
+}
+
+packet LeReadResolvingListSizeComplete : CommandComplete (command_op_code = LE_READ_RESOLVING_LIST_SIZE) {
+  status : ErrorCode,
 }
 
 packet LeReadPeerResolvableAddress : LeSecurityCommand (op_code = LE_READ_PEER_RESOLVABLE_ADDRESS) {
-  _payload_,  // placeholder (unimplemented)
+  peer_identity_address_type : PeerAddressType,
+  peer_identity_address : Address,
+}
+
+packet LeReadPeerResolvableAddressComplete : CommandComplete (command_op_code = LE_READ_PEER_RESOLVABLE_ADDRESS) {
+  status : ErrorCode,
+  peer_resolvable_address : Address,
 }
 
 packet LeReadLocalResolvableAddress : LeSecurityCommand (op_code = LE_READ_LOCAL_RESOLVABLE_ADDRESS) {
-  _payload_,  // placeholder (unimplemented)
+  peer_identity_address_type : PeerAddressType,
+  peer_identity_address : Address,
+}
+
+packet LeReadLocalResolvableAddressComplete : CommandComplete (command_op_code = LE_READ_LOCAL_RESOLVABLE_ADDRESS) {
+  status : ErrorCode,
+  local_resolvable_address : Address,
 }
 
 packet LeSetAddressResolutionEnable : LeSecurityCommand (op_code = LE_SET_ADDRESS_RESOLUTION_ENABLE) {
-  _payload_,  // placeholder (unimplemented)
+  address_resolution_enable : Enable,
+}
+
+packet LeSetAddressResolutionEnableComplete : CommandComplete (command_op_code = LE_SET_ADDRESS_RESOLUTION_ENABLE) {
+  status : ErrorCode,
 }
 
 packet LeSetResolvablePrivateAddressTimeout : LeSecurityCommand (op_code = LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT) {
-  _payload_,  // placeholder (unimplemented)
+  rpa_timeout : 16, // RPA_Timeout measured in seconds 0x0001 to 0xA1B8 1s to 11.5 hours
+}
+
+packet LeSetResolvablePrivateAddressTimeoutComplete : CommandComplete (command_op_code = LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT) {
+  status : ErrorCode,
 }
 
 packet LeReadMaximumDataLength : CommandPacket (op_code = LE_READ_MAXIMUM_DATA_LENGTH) {
@@ -2582,7 +2706,6 @@
   supported_max_rx_time: 16,
 }
 
-
 packet LeReadMaximumDataLengthComplete : CommandComplete (command_op_code = LE_READ_MAXIMUM_DATA_LENGTH) {
   status : ErrorCode,
   le_maximum_data_length : LeMaximumDataLength,
@@ -2925,14 +3048,34 @@
   _payload_,  // placeholder (unimplemented)
 }
 
+enum PrivacyMode : 8 {
+  NETWORK = 0,
+  DEVICE = 1,
+}
+
 packet LeSetPrivacyMode : LeSecurityCommand (op_code = LE_SET_PRIVACY_MODE) {
-  _payload_,  // placeholder (unimplemented)
+  peer_identity_address_type : PeerAddressType,
+  peer_identity_address : Address,
+  privacy_mode : PrivacyMode,
 }
 
 packet LeSetPrivacyModeComplete : CommandComplete (command_op_code = LE_SET_PRIVACY_MODE) {
   status : ErrorCode,
 }
 
+enum UseDebugKey : 8 {
+  USE_GENERATED_KEY = 0,
+  USE_DEBUG_KEY = 1,
+}
+
+packet LeGenerateDhkeyCommand : LeSecurityCommand (op_code = LE_GENERATE_DHKEY_COMMAND) {
+  remote_p_256_public_key : 8[64],
+  key_type : UseDebugKey,
+}
+
+packet LeGenerateDhkeyCommandStatus : CommandStatus (command_op_code = LE_GENERATE_DHKEY_COMMAND) {
+}
+
   // VENDOR_SPECIFIC
 packet LeGetVendorCapabilities : VendorCommand (op_code = LE_GET_VENDOR_CAPABILITIES) {
 }
@@ -3073,7 +3216,7 @@
   SERVICE_DATA = 0x07,
 }
 
-packet LeAdvFilter : VendorCommand (op_code = LE_ADV_FILTER) {
+packet LeAdvFilter : LeScanningCommand (op_code = LE_ADV_FILTER) {
   apcf_opcode : ApcfOpcode,
   _body_,
 }
@@ -3316,7 +3459,7 @@
 }
 
 packet LoopbackCommand : EventPacket (event_code = LOOPBACK_COMMAND){
-  _payload_, // placeholder (unimplemented)
+  _payload_, // Command packet, truncated if it was longer than 252 bytes
 }
 
 packet DataBufferOverflow : EventPacket (event_code = DATA_BUFFER_OVERFLOW){
diff --git a/gd/hci/le_scanning_manager.cc b/gd/hci/le_scanning_manager.cc
index ad88b44..cbe704a 100644
--- a/gd/hci/le_scanning_manager.cc
+++ b/gd/hci/le_scanning_manager.cc
@@ -29,6 +29,9 @@
 namespace bluetooth {
 namespace hci {
 
+constexpr uint16_t kDefaultLeScanWindow = 4800;
+constexpr uint16_t kDefaultLeScanInterval = 4800;
+
 const ModuleFactory LeScanningManager::Factory = ModuleFactory([]() { return new LeScanningManager(); });
 
 enum class ScanApiType {
@@ -109,8 +112,8 @@
   void configure_scan() {
     std::vector<PhyScanParameters> parameter_vector;
     PhyScanParameters phy_scan_parameters;
-    phy_scan_parameters.le_scan_window_ = 0;
-    phy_scan_parameters.le_scan_interval_ = 0;
+    phy_scan_parameters.le_scan_window_ = kDefaultLeScanWindow;
+    phy_scan_parameters.le_scan_interval_ = kDefaultLeScanInterval;
     phy_scan_parameters.le_scan_type_ = LeScanType::ACTIVE;
     parameter_vector.push_back(phy_scan_parameters);
     uint8_t phys_in_use = 1;
@@ -255,4 +258,4 @@
 }
 
 }  // namespace hci
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/gd/l2cap/classic/cert/cert.cc b/gd/l2cap/classic/cert/cert.cc
index abb3561..4f28319 100644
--- a/gd/l2cap/classic/cert/cert.cc
+++ b/gd/l2cap/classic/cert/cert.cc
@@ -164,10 +164,10 @@
     if (request->retransmission_config().mode() == ChannelRetransmissionFlowControlMode::ERTM) {
       auto option = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
       option->mode_ = RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
-      option->tx_window_size_ = 10;
-      option->max_transmit_ = 20;
-      option->retransmission_time_out_ = 2000;
-      option->monitor_time_out_ = 12000;
+      option->tx_window_size_ = 5;
+      option->max_transmit_ = 1;
+      option->retransmission_time_out_ = 1000;
+      option->monitor_time_out_ = 2000;
       option->maximum_pdu_size_ = 1010;
       config.push_back(std::move(option));
     }
@@ -407,6 +407,16 @@
         LogEvent(response);
         break;
       }
+      case CommandCode::DISCONNECTION_REQUEST: {
+        DisconnectionRequestView view = DisconnectionRequestView::Create(control_view);
+        ASSERT(view.IsValid());
+        FetchL2capLogResponse response;
+        response.mutable_disconnection_request()->set_signal_id(control_view.GetIdentifier());
+        response.mutable_disconnection_request()->set_dcid(view.GetDestinationCid());
+        response.mutable_disconnection_request()->set_scid(view.GetSourceCid());
+        LogEvent(response);
+        break;
+      }
       case CommandCode::DISCONNECTION_RESPONSE: {
         DisconnectionResponseView view = DisconnectionResponseView::Create(control_view);
         ASSERT(view.IsValid());
diff --git a/gd/l2cap/classic/cert/simple_l2cap_test.py b/gd/l2cap/classic/cert/simple_l2cap_test.py
index 607cfb2..3320694 100644
--- a/gd/l2cap/classic/cert/simple_l2cap_test.py
+++ b/gd/l2cap/classic/cert/simple_l2cap_test.py
@@ -142,6 +142,7 @@
             self.cert_device.l2cap.SendConfigurationResponse(l2cap_cert_pb2.ConfigurationResponse(
                 scid=dcid,
                 signal_id=log.signal_id,
+                retransmission_config=l2cap_cert_pb2.ChannelRetransmissionFlowControlConfig(mode=self.retransmission_mode)
                 ))
         log_event_handler.on(is_configuration_request, handle_configuration_request)
 
@@ -404,3 +405,55 @@
         assert info_response[0][0] == signal_id
         assert info_response[0][1] == expected_log_type
         assert info_response[0][2] | expected_mask == expected_mask
+
+    def test_transmit_i_frames(self):
+        """
+        L2CAP/ERM/BV-01-C [Transmit I-frames]
+        """
+        self.retransmission_mode = l2cap_cert_pb2.ChannelRetransmissionFlowControlMode.ERTM
+        self.device_under_test.l2cap.RegisterChannel(l2cap_facade_pb2.RegisterChannelRequest(channel=2))
+        self.device_under_test.l2cap.SetDynamicChannel(l2cap_facade_pb2.SetEnableDynamicChannelRequest(psm=0x33, retransmission_mode=l2cap_facade_pb2.RetransmissionFlowControlMode.ERTM))
+        self._setup_link()
+        scid = 0x0101
+        self._open_channel(scid=scid)
+        self.device_under_test.l2cap.SendDynamicChannelPacket(l2cap_facade_pb2.DynamicChannelPacket(psm=0x33, payload=b'abc'))
+        self.cert_device.l2cap.SendSFrame(l2cap_cert_pb2.SFrame(channel=self.scid_dcid_map[scid], req_seq=1, s=0))
+        self.device_under_test.l2cap.SendDynamicChannelPacket(l2cap_facade_pb2.DynamicChannelPacket(psm=0x33, payload=b'abc'))
+        self.cert_device.l2cap.SendSFrame(l2cap_cert_pb2.SFrame(channel=self.scid_dcid_map[scid], req_seq=2, s=0))
+        self.device_under_test.l2cap.SendDynamicChannelPacket(l2cap_facade_pb2.DynamicChannelPacket(psm=0x33, payload=b'abc'))
+        self.cert_device.l2cap.SendSFrame(l2cap_cert_pb2.SFrame(channel=self.scid_dcid_map[scid], req_seq=3, s=0))
+        data_received = []
+        event_handler = EventHandler()
+        def on_data_received(log):
+            log = log.data_packet
+            data_received.append((log.channel, log.payload))
+        event_handler.on(lambda log : log.HasField("data_packet"), on_data_received)
+        logs = self.cert_device.l2cap.FetchL2capLog(l2cap_cert_pb2.FetchL2capLogRequest())
+        event_handler.execute(logs)
+        assert len(data_received) == 3
+
+    def test_s_frame_transmissions_exceed_max_transmit(self):
+        """
+        L2CAP/ERM/BV-11-C [S-Frame Transmissions Exceed MaxTransmit]
+        """
+        self.retransmission_mode = l2cap_cert_pb2.ChannelRetransmissionFlowControlMode.ERTM
+        self.device_under_test.l2cap.RegisterChannel(l2cap_facade_pb2.RegisterChannelRequest(channel=2))
+        self.device_under_test.l2cap.SetDynamicChannel(l2cap_facade_pb2.SetEnableDynamicChannelRequest(psm=0x33, retransmission_mode=l2cap_facade_pb2.RetransmissionFlowControlMode.ERTM))
+        self._setup_link()
+        scid = 0x0101
+        self._open_channel(scid=scid)
+        self.device_under_test.l2cap.SendDynamicChannelPacket(l2cap_facade_pb2.DynamicChannelPacket(psm=0x33, payload=b'abc'))
+        # Retransmission timer = 1, 1 * monitor timer = 2, so total timeout is 3
+        time.sleep(4)
+        disconnect_request = []
+        event_handler = EventHandler()
+
+        def on_disconnect_req(log):
+            log = log.disconnection_request
+            disconnect_request.append((log.dcid, log.scid))
+        event_handler.on(is_disconnection_request, on_disconnect_req)
+
+        logs = self.cert_device.l2cap.FetchL2capLog(l2cap_cert_pb2.FetchL2capLogRequest())
+        event_handler.execute(logs)
+        assert len(disconnect_request) == 1, "No disconnect request received"
+        assert disconnect_request[0] == (scid, self.scid_dcid_map[scid]), "Incorrect disconnect request received: scid %r, dcid %r" % (disconnect_request[0][0], disconnect_request[0][1])
diff --git a/gd/l2cap/classic/dynamic_channel.h b/gd/l2cap/classic/dynamic_channel.h
new file mode 100644
index 0000000..0bd5a82
--- /dev/null
+++ b/gd/l2cap/classic/dynamic_channel.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+
+#include "l2cap/dynamic_channel.h"
+
+namespace bluetooth {
+namespace l2cap {
+namespace classic {
+
+using DynamicChannel = l2cap::DynamicChannel;
+
+}  // namespace classic
+}  // namespace l2cap
+}  // namespace bluetooth
diff --git a/gd/l2cap/classic/dynamic_channel_manager.h b/gd/l2cap/classic/dynamic_channel_manager.h
index 4810270..340d68d 100644
--- a/gd/l2cap/classic/dynamic_channel_manager.h
+++ b/gd/l2cap/classic/dynamic_channel_manager.h
@@ -19,9 +19,9 @@
 
 #include "hci/acl_manager.h"
 #include "hci/address.h"
+#include "l2cap/classic/dynamic_channel.h"
 #include "l2cap/classic/dynamic_channel_configuration_option.h"
 #include "l2cap/classic/dynamic_channel_service.h"
-#include "l2cap/dynamic_channel.h"
 #include "l2cap/l2cap_packets.h"
 #include "l2cap/psm.h"
 #include "l2cap/security_policy.h"
diff --git a/gd/l2cap/classic/internal/dynamic_channel_service_impl.h b/gd/l2cap/classic/internal/dynamic_channel_service_impl.h
index 672d24b..2fcf3fc 100644
--- a/gd/l2cap/classic/internal/dynamic_channel_service_impl.h
+++ b/gd/l2cap/classic/internal/dynamic_channel_service_impl.h
@@ -18,10 +18,10 @@
 
 #include "common/bind.h"
 
+#include "l2cap/classic/dynamic_channel.h"
 #include "l2cap/classic/dynamic_channel_configuration_option.h"
 #include "l2cap/classic/dynamic_channel_manager.h"
 #include "l2cap/classic/dynamic_channel_service.h"
-#include "l2cap/dynamic_channel.h"
 
 namespace bluetooth {
 namespace l2cap {
diff --git a/gd/l2cap/classic/internal/link.cc b/gd/l2cap/classic/internal/link.cc
index a23f5ec..142e32e 100644
--- a/gd/l2cap/classic/internal/link.cc
+++ b/gd/l2cap/classic/internal/link.cc
@@ -34,8 +34,9 @@
            DynamicChannelServiceManagerImpl* dynamic_service_manager,
            FixedChannelServiceManagerImpl* fixed_service_manager)
     : l2cap_handler_(l2cap_handler), acl_connection_(std::move(acl_connection)),
-      data_pipeline_manager_(l2cap_handler, acl_connection_->GetAclQueueEnd()), parameter_provider_(parameter_provider),
-      dynamic_service_manager_(dynamic_service_manager), fixed_service_manager_(fixed_service_manager),
+      data_pipeline_manager_(l2cap_handler, this, acl_connection_->GetAclQueueEnd()),
+      parameter_provider_(parameter_provider), dynamic_service_manager_(dynamic_service_manager),
+      fixed_service_manager_(fixed_service_manager),
       signalling_manager_(l2cap_handler_, this, &data_pipeline_manager_, dynamic_service_manager_,
                           &dynamic_channel_allocator_, fixed_service_manager_) {
   ASSERT(l2cap_handler_ != nullptr);
@@ -91,6 +92,7 @@
   auto channel = dynamic_channel_allocator_.AllocateChannel(psm, remote_cid, security_policy);
   if (channel != nullptr) {
     data_pipeline_manager_.AttachChannel(channel->GetCid(), channel);
+    RefreshRefCount();
   }
   channel->local_initiated_ = false;
   return channel;
@@ -101,6 +103,7 @@
   auto channel = dynamic_channel_allocator_.AllocateReservedChannel(reserved_cid, psm, remote_cid, security_policy);
   if (channel != nullptr) {
     data_pipeline_manager_.AttachChannel(channel->GetCid(), channel);
+    RefreshRefCount();
   }
   channel->local_initiated_ = true;
   return channel;
@@ -118,6 +121,7 @@
   }
   data_pipeline_manager_.DetachChannel(cid);
   dynamic_channel_allocator_.FreeChannel(cid);
+  RefreshRefCount();
 }
 
 void Link::RefreshRefCount() {
diff --git a/gd/l2cap/classic/internal/signalling_manager.h b/gd/l2cap/classic/internal/signalling_manager.h
index 81c8c31..3ae95dd 100644
--- a/gd/l2cap/classic/internal/signalling_manager.h
+++ b/gd/l2cap/classic/internal/signalling_manager.h
@@ -112,7 +112,6 @@
   l2cap::internal::DynamicChannelAllocator* channel_allocator_;
   FixedChannelServiceManagerImpl* fixed_service_manager_;
   std::unique_ptr<os::EnqueueBuffer<packet::BasePacketBuilder>> enqueue_buffer_;
-  PendingCommand last_sent_command_;
   std::queue<PendingCommand> pending_commands_;
   os::Alarm alarm_;
   SignalId next_signal_id_ = kInitialSignalId;
diff --git a/gd/l2cap/internal/data_pipeline_manager.cc b/gd/l2cap/internal/data_pipeline_manager.cc
index 1c8d973..674df95 100644
--- a/gd/l2cap/internal/data_pipeline_manager.cc
+++ b/gd/l2cap/internal/data_pipeline_manager.cc
@@ -29,7 +29,7 @@
 void DataPipelineManager::AttachChannel(Cid cid, std::shared_ptr<ChannelImpl> channel) {
   ASSERT(sender_map_.find(cid) == sender_map_.end());
   sender_map_.emplace(std::piecewise_construct, std::forward_as_tuple(cid),
-                      std::forward_as_tuple(handler_, scheduler_.get(), channel));
+                      std::forward_as_tuple(handler_, link_, scheduler_.get(), channel));
 }
 
 void DataPipelineManager::DetachChannel(Cid cid) {
diff --git a/gd/l2cap/internal/data_pipeline_manager.h b/gd/l2cap/internal/data_pipeline_manager.h
index fffbfc7..557a741 100644
--- a/gd/l2cap/internal/data_pipeline_manager.h
+++ b/gd/l2cap/internal/data_pipeline_manager.h
@@ -39,11 +39,12 @@
 namespace bluetooth {
 namespace l2cap {
 namespace internal {
+class ILink;
 
 /**
  * Manages data pipeline from channel queue end to link queue end, per link.
  * Contains a Scheduler and Receiver per link.
- * Contains a Sender and its corrsponding DataController per attached channel.
+ * Contains a Sender and its corresponding DataController per attached channel.
  */
 class DataPipelineManager {
  public:
@@ -54,8 +55,8 @@
   using LowerDequeue = UpperEnqueue;
   using LowerQueueUpEnd = common::BidiQueueEnd<LowerEnqueue, LowerDequeue>;
 
-  DataPipelineManager(os::Handler* handler, LowerQueueUpEnd* link_queue_up_end)
-      : handler_(handler), scheduler_(std::make_unique<Fifo>(this, link_queue_up_end, handler)),
+  DataPipelineManager(os::Handler* handler, ILink* link, LowerQueueUpEnd* link_queue_up_end)
+      : handler_(handler), link_(link), scheduler_(std::make_unique<Fifo>(this, link_queue_up_end, handler)),
         receiver_(link_queue_up_end, handler, this) {}
 
   virtual void AttachChannel(Cid cid, std::shared_ptr<ChannelImpl> channel);
@@ -67,6 +68,7 @@
 
  private:
   os::Handler* handler_;
+  ILink* link_;
   std::unique_ptr<Scheduler> scheduler_;
   Receiver receiver_;
   std::unordered_map<Cid, Sender> sender_map_;
diff --git a/gd/l2cap/internal/data_pipeline_manager_mock.h b/gd/l2cap/internal/data_pipeline_manager_mock.h
index f5a24f4..9c2f6c8 100644
--- a/gd/l2cap/internal/data_pipeline_manager_mock.h
+++ b/gd/l2cap/internal/data_pipeline_manager_mock.h
@@ -32,7 +32,7 @@
 class MockDataPipelineManager : public DataPipelineManager {
  public:
   MockDataPipelineManager(os::Handler* handler, LowerQueueUpEnd* link_queue_up_end)
-      : DataPipelineManager(handler, link_queue_up_end) {}
+      : DataPipelineManager(handler, nullptr, link_queue_up_end) {}
   MOCK_METHOD(void, AttachChannel, (Cid, std::shared_ptr<ChannelImpl>), (override));
   MOCK_METHOD(void, DetachChannel, (Cid), (override));
   MOCK_METHOD(DataController*, GetDataController, (Cid), (override));
diff --git a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc
index 97f9702..74e8a2f 100644
--- a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc
+++ b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.cc
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include "common/bind.h"
+#include "l2cap/internal/ilink.h"
 #include "os/alarm.h"
 #include "packet/fragmenting_inserter.h"
 #include "packet/raw_builder.h"
@@ -28,10 +29,10 @@
 namespace bluetooth {
 namespace l2cap {
 namespace internal {
-ErtmController::ErtmController(Cid cid, Cid remote_cid, UpperQueueDownEnd* channel_queue_end, os::Handler* handler,
-                               Scheduler* scheduler)
-    : cid_(cid), remote_cid_(remote_cid), enqueue_buffer_(channel_queue_end), handler_(handler), scheduler_(scheduler),
-      pimpl_(std::make_unique<impl>(this, handler)) {}
+ErtmController::ErtmController(ILink* link, Cid cid, Cid remote_cid, UpperQueueDownEnd* channel_queue_end,
+                               os::Handler* handler, Scheduler* scheduler)
+    : link_(link), cid_(cid), remote_cid_(remote_cid), enqueue_buffer_(channel_queue_end), handler_(handler),
+      scheduler_(scheduler), pimpl_(std::make_unique<impl>(this, handler)) {}
 
 ErtmController::~ErtmController() = default;
 
@@ -153,7 +154,7 @@
       send_rr_or_rnr(Poll::POLL);
       // send rr or rnr(p=1)
       retry_count_ = 1;
-      start_retrans_timer();
+      start_monitor_timer();
       tx_state_ = TxState::WAIT_F;
     }
   }
@@ -770,7 +771,7 @@
   }
 
   void CloseChannel() {
-    // TODO: Needs a reference to signaller
+    controller_->close_channel();
   }
 
   void pop_srej_list() {
@@ -1005,7 +1006,7 @@
 }
 
 void ErtmController::close_channel() {
-  // TODO: Get a reference to signalling manager
+  link_->SendDisconnectionRequest(cid_, remote_cid_);
 }
 
 size_t ErtmController::CopyablePacketBuilder::size() const {
diff --git a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h
index dd1ca64..184d6c1 100644
--- a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h
+++ b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h
@@ -36,13 +36,14 @@
 namespace bluetooth {
 namespace l2cap {
 namespace internal {
+class ILink;
 
 class ErtmController : public DataController {
  public:
   using UpperEnqueue = packet::PacketView<packet::kLittleEndian>;
   using UpperDequeue = packet::BasePacketBuilder;
   using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>;
-  ErtmController(Cid cid, Cid remote_cid, UpperQueueDownEnd* channel_queue_end, os::Handler* handler,
+  ErtmController(ILink* link, Cid cid, Cid remote_cid, UpperQueueDownEnd* channel_queue_end, os::Handler* handler,
                  Scheduler* scheduler);
   ~ErtmController();
   // Segmentation is handled here
@@ -53,6 +54,7 @@
   void SetRetransmissionAndFlowControlOptions(const RetransmissionAndFlowControlConfigurationOption& option) override;
 
  private:
+  ILink* link_;
   Cid cid_;
   Cid remote_cid_;
   os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_;
diff --git a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc
index e1b5818..f813898 100644
--- a/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc
+++ b/gd/l2cap/internal/enhanced_retransmission_mode_channel_data_controller_test.cc
@@ -18,6 +18,7 @@
 
 #include <gtest/gtest.h>
 
+#include "l2cap/internal/ilink_mock.h"
 #include "l2cap/internal/scheduler_mock.h"
 #include "l2cap/l2cap_packets.h"
 #include "packet/raw_builder.h"
@@ -73,7 +74,8 @@
 TEST_F(ErtmDataControllerTest, transmit_no_fcs) {
   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
   testing::MockScheduler scheduler;
-  ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+  testing::MockILink link;
+  ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
   EXPECT_CALL(scheduler, OnPacketsReady(1, 1));
   controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'}));
   auto next_packet = controller.GetNextPacket();
@@ -95,7 +97,8 @@
 TEST_F(ErtmDataControllerTest, receive_no_fcs) {
   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
   testing::MockScheduler scheduler;
-  ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+  testing::MockILink link;
+  ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
   auto segment = CreateSdu({'a', 'b', 'c', 'd'});
   auto builder = EnhancedInformationFrameBuilder::Create(1, 0, Final::NOT_SET, 0,
                                                          SegmentationAndReassembly::UNSEGMENTED, std::move(segment));
@@ -111,7 +114,8 @@
 TEST_F(ErtmDataControllerTest, reassemble_valid_sdu) {
   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
   testing::MockScheduler scheduler;
-  ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+  testing::MockILink link;
+  ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
   auto segment1 = CreateSdu({'a'});
   auto segment2 = CreateSdu({'b', 'c'});
   auto segment3 = CreateSdu({'d', 'e', 'f'});
@@ -133,10 +137,11 @@
   EXPECT_EQ(data, "abcdef");
 }
 
-TEST_F(ErtmDataControllerTest, reassemble_invalid_sdu_size_in_start_frame) {
+TEST_F(ErtmDataControllerTest, reassemble_invalid_sdu_size_in_start_frame_will_disconnect) {
   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
   testing::MockScheduler scheduler;
-  ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+  testing::MockILink link;
+  ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
   auto segment1 = CreateSdu({'a'});
   auto segment2 = CreateSdu({'b', 'c'});
   auto segment3 = CreateSdu({'d', 'e', 'f'});
@@ -150,6 +155,7 @@
   auto builder3 = EnhancedInformationFrameBuilder::Create(1, 2, Final::NOT_SET, 0, SegmentationAndReassembly::END,
                                                           std::move(segment3));
   base_view = GetPacketView(std::move(builder3));
+  EXPECT_CALL(link, SendDisconnectionRequest(1, 1));
   controller.OnPdu(base_view);
   sync_handler(queue_handler_);
   auto payload = channel_queue.GetUpEnd()->TryDequeue();
@@ -159,7 +165,8 @@
 TEST_F(ErtmDataControllerTest, transmit_with_fcs) {
   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
   testing::MockScheduler scheduler;
-  ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+  testing::MockILink link;
+  ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
   controller.EnableFcs(true);
   EXPECT_CALL(scheduler, OnPacketsReady(1, 1));
   controller.OnSdu(CreateSdu({'a', 'b', 'c', 'd'}));
@@ -182,7 +189,8 @@
 TEST_F(ErtmDataControllerTest, receive_packet_with_fcs) {
   common::BidiQueue<Scheduler::UpperEnqueue, Scheduler::UpperDequeue> channel_queue{10};
   testing::MockScheduler scheduler;
-  ErtmController controller{1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
+  testing::MockILink link;
+  ErtmController controller{&link, 1, 1, channel_queue.GetDownEnd(), queue_handler_, &scheduler};
   controller.EnableFcs(true);
   auto segment = CreateSdu({'a', 'b', 'c', 'd'});
   auto builder = EnhancedInformationFrameWithFcsBuilder::Create(
diff --git a/gd/l2cap/internal/ilink_mock.h b/gd/l2cap/internal/ilink_mock.h
new file mode 100644
index 0000000..15c642b
--- /dev/null
+++ b/gd/l2cap/internal/ilink_mock.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+
+#include "l2cap/internal/ilink.h"
+
+#include <gmock/gmock.h>
+
+// Unit test interfaces
+namespace bluetooth {
+namespace l2cap {
+namespace internal {
+namespace testing {
+
+class MockILink : public ILink {
+ public:
+  MOCK_METHOD(hci::AddressWithType, GetDevice, (), (override));
+  MOCK_METHOD(void, SendDisconnectionRequest, (Cid, Cid), (override));
+};
+
+}  // namespace testing
+}  // namespace internal
+}  // namespace l2cap
+}  // namespace bluetooth
diff --git a/gd/l2cap/internal/sender.cc b/gd/l2cap/internal/sender.cc
index 1c146cf..d4884b2 100644
--- a/gd/l2cap/internal/sender.cc
+++ b/gd/l2cap/internal/sender.cc
@@ -28,9 +28,9 @@
 namespace l2cap {
 namespace internal {
 
-Sender::Sender(os::Handler* handler, Scheduler* scheduler, std::shared_ptr<ChannelImpl> channel)
-    : handler_(handler), queue_end_(channel->GetQueueDownEnd()), scheduler_(scheduler), channel_id_(channel->GetCid()),
-      remote_channel_id_(channel->GetRemoteCid()),
+Sender::Sender(os::Handler* handler, ILink* link, Scheduler* scheduler, std::shared_ptr<ChannelImpl> channel)
+    : handler_(handler), link_(link), queue_end_(channel->GetQueueDownEnd()), scheduler_(scheduler),
+      channel_id_(channel->GetCid()), remote_channel_id_(channel->GetRemoteCid()),
       data_controller_(std::make_unique<BasicModeDataController>(channel_id_, remote_channel_id_, queue_end_, handler_,
                                                                  scheduler_)) {
   try_register_dequeue();
@@ -82,7 +82,7 @@
   }
   if (mode == RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION) {
     data_controller_ =
-        std::make_unique<ErtmController>(channel_id_, remote_channel_id_, queue_end_, handler_, scheduler_);
+        std::make_unique<ErtmController>(link_, channel_id_, remote_channel_id_, queue_end_, handler_, scheduler_);
     data_controller_->SetRetransmissionAndFlowControlOptions(config.local_retransmission_and_flow_control_);
     data_controller_->EnableFcs(config.fcs_type_ == FcsType::DEFAULT);
     return;
diff --git a/gd/l2cap/internal/sender.h b/gd/l2cap/internal/sender.h
index 46e0006..0e8e78d 100644
--- a/gd/l2cap/internal/sender.h
+++ b/gd/l2cap/internal/sender.h
@@ -37,6 +37,7 @@
 namespace l2cap {
 namespace internal {
 class Scheduler;
+class ILink;
 
 /**
  * A middle layer between L2CAP channel and outgoing packet scheduler.
@@ -48,7 +49,7 @@
   using UpperDequeue = packet::BasePacketBuilder;
   using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>;
 
-  Sender(os::Handler* handler, Scheduler* scheduler, std::shared_ptr<ChannelImpl> channel);
+  Sender(os::Handler* handler, ILink* link, Scheduler* scheduler, std::shared_ptr<ChannelImpl> channel);
   ~Sender();
 
   /**
@@ -67,6 +68,7 @@
 
  private:
   os::Handler* handler_;
+  ILink* link_;
   UpperQueueDownEnd* queue_end_;
   Scheduler* scheduler_;
   const Cid channel_id_;
diff --git a/gd/l2cap/internal/sender_test.cc b/gd/l2cap/internal/sender_test.cc
index cecdfa4..bd24fd4 100644
--- a/gd/l2cap/internal/sender_test.cc
+++ b/gd/l2cap/internal/sender_test.cc
@@ -77,7 +77,7 @@
     EXPECT_CALL(*mock_channel_, GetQueueDownEnd()).WillRepeatedly(Return(channel_queue_.GetDownEnd()));
     EXPECT_CALL(*mock_channel_, GetCid()).WillRepeatedly(Return(cid_));
     EXPECT_CALL(*mock_channel_, GetRemoteCid()).WillRepeatedly(Return(cid_));
-    sender_ = new Sender(queue_handler_, &scheduler_, mock_channel_);
+    sender_ = new Sender(queue_handler_, nullptr, &scheduler_, mock_channel_);
   }
 
   void TearDown() override {
diff --git a/gd/l2cap/le/dynamic_channel.h b/gd/l2cap/le/dynamic_channel.h
new file mode 100644
index 0000000..db1d822
--- /dev/null
+++ b/gd/l2cap/le/dynamic_channel.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+
+#include "l2cap/dynamic_channel.h"
+
+namespace bluetooth {
+namespace l2cap {
+namespace le {
+
+using DynamicChannel = l2cap::DynamicChannel;
+
+}  // namespace le
+}  // namespace l2cap
+}  // namespace bluetooth
diff --git a/gd/l2cap/le/internal/link.h b/gd/l2cap/le/internal/link.h
index 2807353..945f54a 100644
--- a/gd/l2cap/le/internal/link.h
+++ b/gd/l2cap/le/internal/link.h
@@ -37,7 +37,7 @@
   Link(os::Handler* l2cap_handler, std::unique_ptr<hci::AclConnection> acl_connection,
        l2cap::internal::ParameterProvider* parameter_provider)
       : l2cap_handler_(l2cap_handler), acl_connection_(std::move(acl_connection)),
-        data_pipeline_manager_(l2cap_handler, acl_connection_->GetAclQueueEnd()),
+        data_pipeline_manager_(l2cap_handler, this, acl_connection_->GetAclQueueEnd()),
         parameter_provider_(parameter_provider) {
     ASSERT(l2cap_handler_ != nullptr);
     ASSERT(acl_connection_ != nullptr);
diff --git a/gd/shim/l2cap.cc b/gd/shim/l2cap.cc
index 7af8f77..d703972 100644
--- a/gd/shim/l2cap.cc
+++ b/gd/shim/l2cap.cc
@@ -50,7 +50,8 @@
 
 using ServiceInterfaceCallback =
     std::function<void(l2cap::Psm psm, l2cap::classic::DynamicChannelManager::RegistrationResult result)>;
-using ConnectionInterfaceCallback = std::function<void(l2cap::Psm psm, std::unique_ptr<l2cap::DynamicChannel>)>;
+using ConnectionInterfaceCallback =
+    std::function<void(l2cap::Psm psm, std::unique_ptr<l2cap::classic::DynamicChannel>)>;
 
 std::unique_ptr<packet::RawBuilder> MakeUniquePacket(const uint8_t* data, size_t len) {
   packet::RawBuilder builder;
@@ -62,7 +63,7 @@
 
 class ConnectionInterface {
  public:
-  ConnectionInterface(ConnectionInterfaceDescriptor cid, std::unique_ptr<l2cap::DynamicChannel> channel,
+  ConnectionInterface(ConnectionInterfaceDescriptor cid, std::unique_ptr<l2cap::classic::DynamicChannel> channel,
                       os::Handler* handler)
       : cid_(cid), channel_(std::move(channel)), handler_(handler), on_data_ready_callback_(nullptr),
         on_connection_closed_callback_(nullptr), address_(channel_->GetDevice()) {
@@ -138,7 +139,7 @@
 
  private:
   const ConnectionInterfaceDescriptor cid_;
-  const std::unique_ptr<l2cap::DynamicChannel> channel_;
+  const std::unique_ptr<l2cap::classic::DynamicChannel> channel_;
   os::Handler* handler_;
 
   ReadDataReadyCallback on_data_ready_callback_;
@@ -154,7 +155,7 @@
 
 struct ConnectionInterfaceManager {
  public:
-  ConnectionInterfaceDescriptor AddChannel(std::unique_ptr<l2cap::DynamicChannel> channel);
+  ConnectionInterfaceDescriptor AddChannel(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
   void RemoveConnection(ConnectionInterfaceDescriptor cid);
 
   void SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid, ReadDataReadyCallback on_data_ready);
@@ -217,7 +218,8 @@
   return current_connection_interface_descriptor_++;
 }
 
-ConnectionInterfaceDescriptor ConnectionInterfaceManager::AddChannel(std::unique_ptr<l2cap::DynamicChannel> channel) {
+ConnectionInterfaceDescriptor ConnectionInterfaceManager::AddChannel(
+    std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
   if (!HasResources()) {
     return kInvalidConnectionInterfaceDescriptor;
   }
@@ -265,7 +267,7 @@
       : connection_interface_manager_(connection_interface_manager), psm_(psm), address_(address),
         on_open_(std::move(on_open)), completed_(std::move(completed)) {}
 
-  void OnConnectionOpen(std::unique_ptr<l2cap::DynamicChannel> channel) {
+  void OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
     LOG_DEBUG("Local initiated connection is open to device:%s for psm:%hd", address_.ToString().c_str(), psm_);
     ConnectionInterfaceDescriptor cid = connection_interface_manager_->AddChannel(std::move(channel));
     completed_.set_value(cid);
@@ -320,7 +322,7 @@
     completed_.set_value();
   }
 
-  void OnConnectionOpen(std::unique_ptr<l2cap::DynamicChannel> channel) {
+  void OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
     LOG_DEBUG("Remote initiated connection is open from device:%s for psm:%hd", channel->GetDevice().ToString().c_str(),
               psm_);
     hci::Address address = channel->GetDevice();
diff --git a/vendor_libs/test_vendor_lib/model/controller/acl_connection.cc b/vendor_libs/test_vendor_lib/model/controller/acl_connection.cc
index 7e14db6..4f0f132 100644
--- a/vendor_libs/test_vendor_lib/model/controller/acl_connection.cc
+++ b/vendor_libs/test_vendor_lib/model/controller/acl_connection.cc
@@ -18,4 +18,25 @@
 
 using std::shared_ptr;
 
-namespace test_vendor_lib {}  // namespace test_vendor_lib
+namespace test_vendor_lib {
+AclConnection::AclConnection(AddressWithType addr, AddressWithType own_addr,
+                             Phy::Type phy_type)
+    : address_(addr), own_address_(own_addr), type_(phy_type) {}
+
+void AclConnection::Encrypt() { encrypted_ = true; };
+
+bool AclConnection::IsEncrypted() const { return encrypted_; };
+
+AddressWithType AclConnection::GetAddress() const { return address_; }
+
+void AclConnection::SetAddress(AddressWithType address) { address_ = address; }
+
+AddressWithType AclConnection::GetOwnAddress() const { return own_address_; }
+
+void AclConnection::SetOwnAddress(AddressWithType own_addr) {
+  own_address_ = own_addr;
+}
+
+Phy::Type AclConnection::GetPhyType() const { return type_; }
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/acl_connection.h b/vendor_libs/test_vendor_lib/model/controller/acl_connection.h
index cc33c13..12e1779 100644
--- a/vendor_libs/test_vendor_lib/model/controller/acl_connection.h
+++ b/vendor_libs/test_vendor_lib/model/controller/acl_connection.h
@@ -18,50 +18,39 @@
 
 #include <cstdint>
 
-#include "hci/address.h"
+#include "hci/address_with_type.h"
+#include "phy.h"
 
 namespace test_vendor_lib {
 
-using ::bluetooth::hci::Address;
+using ::bluetooth::hci::AddressWithType;
 
 // Model the connection of a device to the controller.
 class AclConnection {
  public:
-  AclConnection(Address addr) : address_(addr), address_type_(0), own_address_type_(0) {}
+  AclConnection(AddressWithType addr, AddressWithType own_addr,
+                Phy::Type phy_type);
 
   virtual ~AclConnection() = default;
 
-  void Encrypt() {
-    encrypted_ = true;
-  };
-  bool IsEncrypted() const {
-    return encrypted_;
-  };
+  void Encrypt();
 
-  Address GetAddress() const {
-    return address_;
-  }
-  void SetAddress(Address address) {
-    address_ = address;
-  }
+  bool IsEncrypted() const;
 
-  uint8_t GetAddressType() const {
-    return address_type_;
-  }
-  void SetAddressType(uint8_t address_type) {
-    address_type_ = address_type;
-  }
-  uint8_t GetOwnAddressType() const {
-    return own_address_type_;
-  }
-  void SetOwnAddressType(uint8_t address_type) {
-    own_address_type_ = address_type;
-  }
+  AddressWithType GetAddress() const;
+
+  void SetAddress(AddressWithType address);
+
+  AddressWithType GetOwnAddress() const;
+
+  void SetOwnAddress(AddressWithType own_addr);
+
+  Phy::Type GetPhyType() const;
 
  private:
-  Address address_;
-  uint8_t address_type_;
-  uint8_t own_address_type_;
+  AddressWithType address_;
+  AddressWithType own_address_;
+  Phy::Type type_{Phy::Type::BR_EDR};
 
   // State variables
   bool encrypted_{false};
diff --git a/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc b/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
index 014015a..d798e78 100644
--- a/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
+++ b/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
@@ -25,6 +25,8 @@
 namespace test_vendor_lib {
 
 using ::bluetooth::hci::Address;
+using ::bluetooth::hci::AddressType;
+using ::bluetooth::hci::AddressWithType;
 
 bool AclConnectionHandler::HasHandle(uint16_t handle) const {
   if (acl_connections_.count(handle) == 0) {
@@ -70,9 +72,16 @@
   return true;
 }
 
-bool AclConnectionHandler::CreatePendingLeConnection(Address addr, uint8_t address_type) {
-  if (IsDeviceConnected(addr, address_type)) {
-    LOG_INFO("%s: %s (type %hhx) is already connected", __func__, addr.ToString().c_str(), address_type);
+bool AclConnectionHandler::CreatePendingLeConnection(AddressWithType addr) {
+  bool device_connected = false;
+  for (auto pair : acl_connections_) {
+    auto connection = std::get<AclConnection>(pair);
+    if (connection.GetAddress() == addr) {
+      device_connected = true;
+    }
+  }
+  if (device_connected) {
+    LOG_INFO("%s: %s is already connected", __func__, addr.ToString().c_str());
     return false;
   }
   if (le_connection_pending_) {
@@ -81,42 +90,44 @@
   }
   le_connection_pending_ = true;
   pending_le_connection_address_ = addr;
-  pending_le_connection_address_type_ = address_type;
   return true;
 }
 
-bool AclConnectionHandler::HasPendingLeConnection(Address addr,
-                                                  uint8_t address_type) const {
-  return le_connection_pending_ && pending_le_connection_address_ == addr &&
-         pending_le_connection_address_type_ == address_type;
+bool AclConnectionHandler::HasPendingLeConnection(AddressWithType addr) const {
+  return le_connection_pending_ && pending_le_connection_address_ == addr;
 }
 
-bool AclConnectionHandler::CancelPendingLeConnection(Address addr, uint8_t address_type) {
-  if (!le_connection_pending_ || pending_le_connection_address_ != addr ||
-      pending_le_connection_address_type_ != address_type) {
+bool AclConnectionHandler::CancelPendingLeConnection(AddressWithType addr) {
+  if (!le_connection_pending_ || pending_le_connection_address_ != addr) {
     return false;
   }
   le_connection_pending_ = false;
-  pending_le_connection_address_ = Address::kEmpty;
-  pending_le_connection_address_type_ = 0xba;
+  pending_le_connection_address_ =
+      AddressWithType{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS};
   return true;
 }
 
-uint16_t AclConnectionHandler::CreateConnection(Address addr) {
+uint16_t AclConnectionHandler::CreateConnection(Address addr,
+                                                Address own_addr) {
   if (CancelPendingConnection(addr)) {
     uint16_t handle = GetUnusedHandle();
-    acl_connections_.emplace(handle, addr);
+    acl_connections_.emplace(
+        handle,
+        AclConnection{
+            AddressWithType{addr, AddressType::PUBLIC_DEVICE_ADDRESS},
+            AddressWithType{own_addr, AddressType::PUBLIC_DEVICE_ADDRESS},
+            Phy::Type::BR_EDR});
     return handle;
   }
   return acl::kReservedHandle;
 }
 
-uint16_t AclConnectionHandler::CreateLeConnection(Address addr, uint8_t address_type, uint8_t own_address_type) {
-  if (CancelPendingLeConnection(addr, address_type)) {
+uint16_t AclConnectionHandler::CreateLeConnection(AddressWithType addr,
+                                                  AddressWithType own_addr) {
+  if (CancelPendingLeConnection(addr)) {
     uint16_t handle = GetUnusedHandle();
-    acl_connections_.emplace(handle, addr);
-    set_own_address_type(handle, own_address_type);
-    SetAddress(handle, addr, address_type);
+    acl_connections_.emplace(
+        handle, AclConnection{addr, own_addr, Phy::Type::LOW_ENERGY});
     return handle;
   }
   return acl::kReservedHandle;
@@ -126,7 +137,7 @@
   return acl_connections_.erase(handle) > 0;
 }
 
-uint16_t AclConnectionHandler::GetHandle(Address addr) const {
+uint16_t AclConnectionHandler::GetHandle(AddressWithType addr) const {
   for (auto pair : acl_connections_) {
     if (std::get<AclConnection>(pair).GetAddress() == addr) {
       return std::get<0>(pair);
@@ -135,41 +146,24 @@
   return acl::kReservedHandle;
 }
 
-Address AclConnectionHandler::GetAddress(uint16_t handle) const {
+uint16_t AclConnectionHandler::GetHandleOnlyAddress(
+    bluetooth::hci::Address addr) const {
+  for (auto pair : acl_connections_) {
+    if (std::get<AclConnection>(pair).GetAddress().GetAddress() == addr) {
+      return std::get<0>(pair);
+    }
+  }
+  return acl::kReservedHandle;
+}
+
+AddressWithType AclConnectionHandler::GetAddress(uint16_t handle) const {
   ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle);
   return acl_connections_.at(handle).GetAddress();
 }
 
-uint8_t AclConnectionHandler::GetAddressType(uint16_t handle) const {
+AddressWithType AclConnectionHandler::GetOwnAddress(uint16_t handle) const {
   ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle);
-  return acl_connections_.at(handle).GetAddressType();
-}
-
-void AclConnectionHandler::set_own_address_type(uint16_t handle, uint8_t address_type) {
-  ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle);
-  acl_connections_.at(handle).SetOwnAddressType(address_type);
-}
-
-uint8_t AclConnectionHandler::GetOwnAddressType(uint16_t handle) const {
-  ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle);
-  return acl_connections_.at(handle).GetOwnAddressType();
-}
-
-bool AclConnectionHandler::IsConnected(uint16_t handle) const {
-  if (!HasHandle(handle)) {
-    return false;
-  }
-  return true;
-}
-
-bool AclConnectionHandler::IsDeviceConnected(Address addr, uint8_t address_type) const {
-  for (auto pair : acl_connections_) {
-    auto connection = std::get<AclConnection>(pair);
-    if (connection.GetAddress() == addr && connection.GetAddressType() == address_type) {
-      return true;
-    }
-  }
-  return false;
+  return acl_connections_.at(handle).GetOwnAddress();
 }
 
 void AclConnectionHandler::Encrypt(uint16_t handle) {
@@ -186,13 +180,20 @@
   return acl_connections_.at(handle).IsEncrypted();
 }
 
-void AclConnectionHandler::SetAddress(uint16_t handle, Address address, uint8_t address_type) {
+void AclConnectionHandler::SetAddress(uint16_t handle,
+                                      AddressWithType address) {
   if (!HasHandle(handle)) {
     return;
   }
   auto connection = acl_connections_.at(handle);
   connection.SetAddress(address);
-  connection.SetAddressType(address_type);
+}
+
+Phy::Type AclConnectionHandler::GetPhyType(uint16_t handle) const {
+  if (!HasHandle(handle)) {
+    return Phy::Type::BR_EDR;
+  }
+  return acl_connections_.at(handle).GetPhyType();
 }
 
 }  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h b/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
index c08f529..0f0b5a7 100644
--- a/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
+++ b/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
@@ -22,59 +22,60 @@
 
 #include "acl_connection.h"
 #include "hci/address.h"
+#include "hci/address_with_type.h"
 #include "include/acl.h"
+#include "phy.h"
 
 namespace test_vendor_lib {
 
-using ::bluetooth::hci::Address;
-
 class AclConnectionHandler {
  public:
   AclConnectionHandler() = default;
 
   virtual ~AclConnectionHandler() = default;
 
-  bool CreatePendingConnection(Address addr, bool authenticate_on_connect);
-  bool HasPendingConnection(Address addr) const;
-  bool CancelPendingConnection(Address addr);
+  bool CreatePendingConnection(bluetooth::hci::Address addr,
+                               bool authenticate_on_connect);
+  bool HasPendingConnection(bluetooth::hci::Address addr) const;
+  bool CancelPendingConnection(bluetooth::hci::Address addr);
   bool AuthenticatePendingConnection() const;
 
-  bool CreatePendingLeConnection(Address addr, uint8_t addr_type);
-  bool HasPendingLeConnection(Address addr, uint8_t addr_type) const;
-  bool CancelPendingLeConnection(Address addr, uint8_t addr_type);
+  bool CreatePendingLeConnection(bluetooth::hci::AddressWithType addr);
+  bool HasPendingLeConnection(bluetooth::hci::AddressWithType addr) const;
+  bool CancelPendingLeConnection(bluetooth::hci::AddressWithType addr);
 
-  uint16_t CreateConnection(Address addr);
-  uint16_t CreateLeConnection(Address addr, uint8_t address_type, uint8_t own_address_type);
+  uint16_t CreateConnection(bluetooth::hci::Address addr,
+                            bluetooth::hci::Address own_addr);
+  uint16_t CreateLeConnection(bluetooth::hci::AddressWithType addr,
+                              bluetooth::hci::AddressWithType own_addr);
   bool Disconnect(uint16_t handle);
   bool HasHandle(uint16_t handle) const;
 
-  uint16_t GetHandle(Address addr) const;
-  Address GetAddress(uint16_t handle) const;
-  uint8_t GetAddressType(uint16_t handle) const;
-  uint8_t GetOwnAddressType(uint16_t handle) const;
-
-  void SetConnected(uint16_t handle, bool connected);
-  bool IsConnected(uint16_t handle) const;
-
-  bool IsDeviceConnected(Address addr, uint8_t address_type = 0) const;
+  uint16_t GetHandle(bluetooth::hci::AddressWithType addr) const;
+  uint16_t GetHandleOnlyAddress(bluetooth::hci::Address addr) const;
+  bluetooth::hci::AddressWithType GetAddress(uint16_t handle) const;
+  bluetooth::hci::AddressWithType GetOwnAddress(uint16_t handle) const;
 
   void Encrypt(uint16_t handle);
   bool IsEncrypted(uint16_t handle) const;
 
-  void SetAddress(uint16_t handle, Address address, uint8_t address_type = 0);  // default to public
+  void SetAddress(uint16_t handle, bluetooth::hci::AddressWithType address);
+
+  Phy::Type GetPhyType(uint16_t handle) const;
 
  private:
   std::unordered_map<uint16_t, AclConnection> acl_connections_;
   bool classic_connection_pending_{false};
-  Address pending_connection_address_{Address::kEmpty};
+  bluetooth::hci::Address pending_connection_address_{
+      bluetooth::hci::Address::kEmpty};
   bool authenticate_pending_classic_connection_{false};
   bool le_connection_pending_{false};
-  Address pending_le_connection_address_{Address::kEmpty};
-  uint8_t pending_le_connection_address_type_{false};
+  bluetooth::hci::AddressWithType pending_le_connection_address_{
+      bluetooth::hci::Address::kEmpty,
+      bluetooth::hci::AddressType::PUBLIC_DEVICE_ADDRESS};
 
   uint16_t GetUnusedHandle();
   uint16_t last_handle_{acl::kReservedHandle - 2};
-  void set_own_address_type(uint16_t handle, uint8_t own_address_type);
 };
 
 }  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
index 95bb202..8b0089f 100644
--- a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
+++ b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
@@ -25,24 +25,12 @@
 #include "os/log.h"
 #include "packet/raw_builder.h"
 
-using bluetooth::hci::ErrorCode;
-using bluetooth::hci::LoopbackMode;
-using bluetooth::hci::OpCode;
+namespace gd_hci = ::bluetooth::hci;
+using gd_hci::ErrorCode;
+using gd_hci::LoopbackMode;
+using gd_hci::OpCode;
 using std::vector;
 
-namespace {
-
-size_t LastNonZero(bluetooth::packet::PacketView<true> view) {
-  for (size_t i = view.size() - 1; i > 0; i--) {
-    if (view[i] != 0) {
-      return i;
-    }
-  }
-  return 0;
-}
-
-}  // namespace
-
 namespace test_vendor_lib {
 constexpr char DualModeController::kControllerPropertiesFile[];
 constexpr uint16_t DualModeController::kSecurityManagerNumKeys;
@@ -81,8 +69,8 @@
   raw_builder_ptr->AddOctets1(
       static_cast<uint8_t>(ErrorCode::UNKNOWN_HCI_COMMAND));
 
-  auto packet = bluetooth::hci::EventPacketBuilder::Create(
-      bluetooth::hci::EventCode::COMMAND_COMPLETE, std::move(raw_builder_ptr));
+  auto packet = gd_hci::EventPacketBuilder::Create(
+      gd_hci::EventCode::COMMAND_COMPLETE, std::move(raw_builder_ptr));
   send_event_(std::move(packet));
 }
 
@@ -100,119 +88,137 @@
         DualModeController::SendLinkLayerPacket(packet, phy_type);
       });
 
-#define SET_HANDLER(opcode, method)                     \
-  active_hci_commands_[static_cast<uint16_t>(opcode)] = \
-      [this](PacketView<true> param) { method(param); };
-  SET_HANDLER(OpCode::RESET, HciReset);
-  SET_HANDLER(OpCode::READ_BUFFER_SIZE, HciReadBufferSize);
-  SET_HANDLER(OpCode::HOST_BUFFER_SIZE, HciHostBufferSize);
-  SET_HANDLER(OpCode::SNIFF_SUBRATING, HciSniffSubrating);
-  SET_HANDLER(OpCode::READ_ENCRYPTION_KEY_SIZE, HciReadEncryptionKeySize);
-  SET_HANDLER(OpCode::READ_LOCAL_VERSION_INFORMATION, HciReadLocalVersionInformation);
-  SET_HANDLER(OpCode::READ_BD_ADDR, HciReadBdAddr);
-  SET_HANDLER(OpCode::READ_LOCAL_SUPPORTED_COMMANDS, HciReadLocalSupportedCommands);
-  SET_HANDLER(OpCode::READ_LOCAL_SUPPORTED_FEATURES, HciReadLocalSupportedFeatures);
-  SET_HANDLER(OpCode::READ_LOCAL_SUPPORTED_CODECS, HciReadLocalSupportedCodecs);
-  SET_HANDLER(OpCode::READ_LOCAL_EXTENDED_FEATURES, HciReadLocalExtendedFeatures);
-  SET_HANDLER(OpCode::READ_REMOTE_EXTENDED_FEATURES, HciReadRemoteExtendedFeatures);
-  SET_HANDLER(OpCode::SWITCH_ROLE, HciSwitchRole);
-  SET_HANDLER(OpCode::READ_REMOTE_SUPPORTED_FEATURES, HciReadRemoteSupportedFeatures);
-  SET_HANDLER(OpCode::READ_CLOCK_OFFSET, HciReadClockOffset);
-  SET_HANDLER(OpCode::IO_CAPABILITY_REQUEST_REPLY, HciIoCapabilityRequestReply);
-  SET_HANDLER(OpCode::USER_CONFIRMATION_REQUEST_REPLY, HciUserConfirmationRequestReply);
-  SET_HANDLER(OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY, HciUserConfirmationRequestNegativeReply);
-  SET_HANDLER(OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, HciIoCapabilityRequestNegativeReply);
-  SET_HANDLER(OpCode::WRITE_SIMPLE_PAIRING_MODE, HciWriteSimplePairingMode);
-  SET_HANDLER(OpCode::WRITE_LE_HOST_SUPPORT, HciWriteLeHostSupport);
+#define SET_HANDLER(opcode, method)                                \
+  active_hci_commands_[opcode] = [this](CommandPacketView param) { \
+    method(param);                                                 \
+  };
+  SET_HANDLER(OpCode::RESET, Reset);
+  SET_HANDLER(OpCode::READ_BUFFER_SIZE, ReadBufferSize);
+  SET_HANDLER(OpCode::HOST_BUFFER_SIZE, HostBufferSize);
+  SET_HANDLER(OpCode::SNIFF_SUBRATING, SniffSubrating);
+  SET_HANDLER(OpCode::READ_ENCRYPTION_KEY_SIZE, ReadEncryptionKeySize);
+  SET_HANDLER(OpCode::READ_LOCAL_VERSION_INFORMATION,
+              ReadLocalVersionInformation);
+  SET_HANDLER(OpCode::READ_BD_ADDR, ReadBdAddr);
+  SET_HANDLER(OpCode::READ_LOCAL_SUPPORTED_COMMANDS,
+              ReadLocalSupportedCommands);
+  SET_HANDLER(OpCode::READ_LOCAL_SUPPORTED_FEATURES,
+              ReadLocalSupportedFeatures);
+  SET_HANDLER(OpCode::READ_LOCAL_SUPPORTED_CODECS, ReadLocalSupportedCodecs);
+  SET_HANDLER(OpCode::READ_LOCAL_EXTENDED_FEATURES, ReadLocalExtendedFeatures);
+  SET_HANDLER(OpCode::READ_REMOTE_EXTENDED_FEATURES,
+              ReadRemoteExtendedFeatures);
+  SET_HANDLER(OpCode::SWITCH_ROLE, SwitchRole);
+  SET_HANDLER(OpCode::READ_REMOTE_SUPPORTED_FEATURES,
+              ReadRemoteSupportedFeatures);
+  SET_HANDLER(OpCode::READ_CLOCK_OFFSET, ReadClockOffset);
+  SET_HANDLER(OpCode::IO_CAPABILITY_REQUEST_REPLY, IoCapabilityRequestReply);
+  SET_HANDLER(OpCode::USER_CONFIRMATION_REQUEST_REPLY,
+              UserConfirmationRequestReply);
+  SET_HANDLER(OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY,
+              UserConfirmationRequestNegativeReply);
+  SET_HANDLER(OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY,
+              IoCapabilityRequestNegativeReply);
+  SET_HANDLER(OpCode::WRITE_SIMPLE_PAIRING_MODE, WriteSimplePairingMode);
+  SET_HANDLER(OpCode::WRITE_LE_HOST_SUPPORT, WriteLeHostSupport);
   SET_HANDLER(OpCode::WRITE_SECURE_CONNECTIONS_HOST_SUPPORT,
-              HciWriteSecureConnectionsHostSupport);
-  SET_HANDLER(OpCode::SET_EVENT_MASK, HciSetEventMask);
-  SET_HANDLER(OpCode::WRITE_INQUIRY_MODE, HciWriteInquiryMode);
-  SET_HANDLER(OpCode::WRITE_PAGE_SCAN_TYPE, HciWritePageScanType);
-  SET_HANDLER(OpCode::WRITE_INQUIRY_SCAN_TYPE, HciWriteInquiryScanType);
-  SET_HANDLER(OpCode::AUTHENTICATION_REQUESTED, HciAuthenticationRequested);
-  SET_HANDLER(OpCode::SET_CONNECTION_ENCRYPTION, HciSetConnectionEncryption);
-  SET_HANDLER(OpCode::CHANGE_CONNECTION_LINK_KEY, HciChangeConnectionLinkKey);
-  SET_HANDLER(OpCode::MASTER_LINK_KEY, HciMasterLinkKey);
-  SET_HANDLER(OpCode::WRITE_AUTHENTICATION_ENABLE, HciWriteAuthenticationEnable);
-  SET_HANDLER(OpCode::READ_AUTHENTICATION_ENABLE, HciReadAuthenticationEnable);
-  SET_HANDLER(OpCode::WRITE_CLASS_OF_DEVICE, HciWriteClassOfDevice);
-  SET_HANDLER(OpCode::WRITE_PAGE_TIMEOUT, HciWritePageTimeout);
-  SET_HANDLER(OpCode::WRITE_LINK_SUPERVISION_TIMEOUT, HciWriteLinkSupervisionTimeout);
-  SET_HANDLER(OpCode::HOLD_MODE, HciHoldMode);
-  SET_HANDLER(OpCode::SNIFF_MODE, HciSniffMode);
-  SET_HANDLER(OpCode::EXIT_SNIFF_MODE, HciExitSniffMode);
-  SET_HANDLER(OpCode::QOS_SETUP, HciQosSetup);
-  SET_HANDLER(OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS, HciWriteDefaultLinkPolicySettings);
-  SET_HANDLER(OpCode::FLOW_SPECIFICATION, HciFlowSpecification);
-  SET_HANDLER(OpCode::WRITE_LINK_POLICY_SETTINGS, HciWriteLinkPolicySettings);
-  SET_HANDLER(OpCode::CHANGE_CONNECTION_PACKET_TYPE, HciChangeConnectionPacketType);
-  SET_HANDLER(OpCode::WRITE_LOCAL_NAME, HciWriteLocalName);
-  SET_HANDLER(OpCode::READ_LOCAL_NAME, HciReadLocalName);
-  SET_HANDLER(OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE, HciWriteExtendedInquiryResponse);
-  SET_HANDLER(OpCode::REFRESH_ENCRYPTION_KEY, HciRefreshEncryptionKey);
-  SET_HANDLER(OpCode::WRITE_VOICE_SETTING, HciWriteVoiceSetting);
-  SET_HANDLER(OpCode::WRITE_CURRENT_IAC_LAP, HciWriteCurrentIacLap);
-  SET_HANDLER(OpCode::WRITE_INQUIRY_SCAN_ACTIVITY, HciWriteInquiryScanActivity);
-  SET_HANDLER(OpCode::WRITE_SCAN_ENABLE, HciWriteScanEnable);
-  SET_HANDLER(OpCode::SET_EVENT_FILTER, HciSetEventFilter);
-  SET_HANDLER(OpCode::INQUIRY, HciInquiry);
-  SET_HANDLER(OpCode::INQUIRY_CANCEL, HciInquiryCancel);
-  SET_HANDLER(OpCode::ACCEPT_CONNECTION_REQUEST, HciAcceptConnectionRequest);
-  SET_HANDLER(OpCode::REJECT_CONNECTION_REQUEST, HciRejectConnectionRequest);
-  SET_HANDLER(OpCode::LINK_KEY_REQUEST_REPLY, HciLinkKeyRequestReply);
-  SET_HANDLER(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, HciLinkKeyRequestNegativeReply);
-  SET_HANDLER(OpCode::DELETE_STORED_LINK_KEY, HciDeleteStoredLinkKey);
-  SET_HANDLER(OpCode::REMOTE_NAME_REQUEST, HciRemoteNameRequest);
-  SET_HANDLER(OpCode::LE_SET_EVENT_MASK, HciLeSetEventMask);
-  SET_HANDLER(OpCode::LE_READ_BUFFER_SIZE, HciLeReadBufferSize);
-  SET_HANDLER(OpCode::LE_READ_LOCAL_SUPPORTED_FEATURES, HciLeReadLocalSupportedFeatures);
-  SET_HANDLER(OpCode::LE_SET_RANDOM_ADDRESS, HciLeSetRandomAddress);
-  SET_HANDLER(OpCode::LE_SET_ADVERTISING_PARAMETERS, HciLeSetAdvertisingParameters);
-  SET_HANDLER(OpCode::LE_SET_ADVERTISING_DATA, HciLeSetAdvertisingData);
-  SET_HANDLER(OpCode::LE_SET_SCAN_RESPONSE_DATA, HciLeSetScanResponseData);
-  SET_HANDLER(OpCode::LE_SET_ADVERTISING_ENABLE, HciLeSetAdvertisingEnable);
-  SET_HANDLER(OpCode::LE_SET_SCAN_PARAMETERS, HciLeSetScanParameters);
-  SET_HANDLER(OpCode::LE_SET_SCAN_ENABLE, HciLeSetScanEnable);
-  SET_HANDLER(OpCode::LE_CREATE_CONNECTION, HciLeCreateConnection);
-  SET_HANDLER(OpCode::CREATE_CONNECTION, HciCreateConnection);
-  SET_HANDLER(OpCode::DISCONNECT, HciDisconnect);
-  SET_HANDLER(OpCode::LE_CREATE_CONNECTION_CANCEL, HciLeConnectionCancel);
-  SET_HANDLER(OpCode::LE_READ_WHITE_LIST_SIZE, HciLeReadWhiteListSize);
-  SET_HANDLER(OpCode::LE_CLEAR_WHITE_LIST, HciLeClearWhiteList);
-  SET_HANDLER(OpCode::LE_ADD_DEVICE_TO_WHITE_LIST, HciLeAddDeviceToWhiteList);
-  SET_HANDLER(OpCode::LE_REMOVE_DEVICE_FROM_WHITE_LIST, HciLeRemoveDeviceFromWhiteList);
-  SET_HANDLER(OpCode::LE_RAND, HciLeRand);
-  SET_HANDLER(OpCode::LE_READ_SUPPORTED_STATES, HciLeReadSupportedStates);
-  SET_HANDLER(OpCode::LE_GET_VENDOR_CAPABILITIES, HciLeVendorCap);
-  SET_HANDLER(OpCode::LE_MULTI_ADVT, HciLeVendorMultiAdv);
-  SET_HANDLER(OpCode::LE_ADV_FILTER, HciLeAdvertisingFilter);
-  SET_HANDLER(OpCode::LE_ENERGY_INFO, HciLeEnergyInfo);
-  SET_HANDLER(OpCode::LE_EXTENDED_SCAN_PARAMS, HciLeExtendedScanParams);
-  SET_HANDLER(OpCode::LE_READ_REMOTE_FEATURES, HciLeReadRemoteFeatures);
-  SET_HANDLER(OpCode::READ_REMOTE_VERSION_INFORMATION, HciReadRemoteVersionInformation);
-  SET_HANDLER(OpCode::LE_CONNECTION_UPDATE, HciLeConnectionUpdate);
-  SET_HANDLER(OpCode::LE_START_ENCRYPTION, HciLeStartEncryption);
+              WriteSecureConnectionsHostSupport);
+  SET_HANDLER(OpCode::SET_EVENT_MASK, SetEventMask);
+  SET_HANDLER(OpCode::WRITE_INQUIRY_MODE, WriteInquiryMode);
+  SET_HANDLER(OpCode::WRITE_PAGE_SCAN_TYPE, WritePageScanType);
+  SET_HANDLER(OpCode::WRITE_INQUIRY_SCAN_TYPE, WriteInquiryScanType);
+  SET_HANDLER(OpCode::AUTHENTICATION_REQUESTED, AuthenticationRequested);
+  SET_HANDLER(OpCode::SET_CONNECTION_ENCRYPTION, SetConnectionEncryption);
+  SET_HANDLER(OpCode::CHANGE_CONNECTION_LINK_KEY, ChangeConnectionLinkKey);
+  SET_HANDLER(OpCode::MASTER_LINK_KEY, MasterLinkKey);
+  SET_HANDLER(OpCode::WRITE_AUTHENTICATION_ENABLE, WriteAuthenticationEnable);
+  SET_HANDLER(OpCode::READ_AUTHENTICATION_ENABLE, ReadAuthenticationEnable);
+  SET_HANDLER(OpCode::WRITE_CLASS_OF_DEVICE, WriteClassOfDevice);
+  SET_HANDLER(OpCode::WRITE_PAGE_TIMEOUT, WritePageTimeout);
+  SET_HANDLER(OpCode::WRITE_LINK_SUPERVISION_TIMEOUT,
+              WriteLinkSupervisionTimeout);
+  SET_HANDLER(OpCode::HOLD_MODE, HoldMode);
+  SET_HANDLER(OpCode::SNIFF_MODE, SniffMode);
+  SET_HANDLER(OpCode::EXIT_SNIFF_MODE, ExitSniffMode);
+  SET_HANDLER(OpCode::QOS_SETUP, QosSetup);
+  SET_HANDLER(OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS,
+              WriteDefaultLinkPolicySettings);
+  SET_HANDLER(OpCode::FLOW_SPECIFICATION, FlowSpecification);
+  SET_HANDLER(OpCode::WRITE_LINK_POLICY_SETTINGS, WriteLinkPolicySettings);
+  SET_HANDLER(OpCode::CHANGE_CONNECTION_PACKET_TYPE,
+              ChangeConnectionPacketType);
+  SET_HANDLER(OpCode::WRITE_LOCAL_NAME, WriteLocalName);
+  SET_HANDLER(OpCode::READ_LOCAL_NAME, ReadLocalName);
+  SET_HANDLER(OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE,
+              WriteExtendedInquiryResponse);
+  SET_HANDLER(OpCode::REFRESH_ENCRYPTION_KEY, RefreshEncryptionKey);
+  SET_HANDLER(OpCode::WRITE_VOICE_SETTING, WriteVoiceSetting);
+  SET_HANDLER(OpCode::WRITE_CURRENT_IAC_LAP, WriteCurrentIacLap);
+  SET_HANDLER(OpCode::WRITE_INQUIRY_SCAN_ACTIVITY, WriteInquiryScanActivity);
+  SET_HANDLER(OpCode::WRITE_SCAN_ENABLE, WriteScanEnable);
+  SET_HANDLER(OpCode::SET_EVENT_FILTER, SetEventFilter);
+  SET_HANDLER(OpCode::INQUIRY, Inquiry);
+  SET_HANDLER(OpCode::INQUIRY_CANCEL, InquiryCancel);
+  SET_HANDLER(OpCode::ACCEPT_CONNECTION_REQUEST, AcceptConnectionRequest);
+  SET_HANDLER(OpCode::REJECT_CONNECTION_REQUEST, RejectConnectionRequest);
+  SET_HANDLER(OpCode::LINK_KEY_REQUEST_REPLY, LinkKeyRequestReply);
+  SET_HANDLER(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY,
+              LinkKeyRequestNegativeReply);
+  SET_HANDLER(OpCode::DELETE_STORED_LINK_KEY, DeleteStoredLinkKey);
+  SET_HANDLER(OpCode::REMOTE_NAME_REQUEST, RemoteNameRequest);
+  SET_HANDLER(OpCode::LE_SET_EVENT_MASK, LeSetEventMask);
+  SET_HANDLER(OpCode::LE_READ_BUFFER_SIZE, LeReadBufferSize);
+  SET_HANDLER(OpCode::LE_READ_LOCAL_SUPPORTED_FEATURES,
+              LeReadLocalSupportedFeatures);
+  SET_HANDLER(OpCode::LE_SET_RANDOM_ADDRESS, LeSetRandomAddress);
+  SET_HANDLER(OpCode::LE_SET_ADVERTISING_PARAMETERS,
+              LeSetAdvertisingParameters);
+  SET_HANDLER(OpCode::LE_SET_ADVERTISING_DATA, LeSetAdvertisingData);
+  SET_HANDLER(OpCode::LE_SET_SCAN_RESPONSE_DATA, LeSetScanResponseData);
+  SET_HANDLER(OpCode::LE_SET_ADVERTISING_ENABLE, LeSetAdvertisingEnable);
+  SET_HANDLER(OpCode::LE_SET_SCAN_PARAMETERS, LeSetScanParameters);
+  SET_HANDLER(OpCode::LE_SET_SCAN_ENABLE, LeSetScanEnable);
+  SET_HANDLER(OpCode::LE_CREATE_CONNECTION, LeCreateConnection);
+  SET_HANDLER(OpCode::CREATE_CONNECTION, CreateConnection);
+  SET_HANDLER(OpCode::DISCONNECT, Disconnect);
+  SET_HANDLER(OpCode::LE_CREATE_CONNECTION_CANCEL, LeConnectionCancel);
+  SET_HANDLER(OpCode::LE_READ_WHITE_LIST_SIZE, LeReadWhiteListSize);
+  SET_HANDLER(OpCode::LE_CLEAR_WHITE_LIST, LeClearWhiteList);
+  SET_HANDLER(OpCode::LE_ADD_DEVICE_TO_WHITE_LIST, LeAddDeviceToWhiteList);
+  SET_HANDLER(OpCode::LE_REMOVE_DEVICE_FROM_WHITE_LIST,
+              LeRemoveDeviceFromWhiteList);
+  SET_HANDLER(OpCode::LE_RAND, LeRand);
+  SET_HANDLER(OpCode::LE_READ_SUPPORTED_STATES, LeReadSupportedStates);
+  SET_HANDLER(OpCode::LE_GET_VENDOR_CAPABILITIES, LeVendorCap);
+  SET_HANDLER(OpCode::LE_MULTI_ADVT, LeVendorMultiAdv);
+  SET_HANDLER(OpCode::LE_ADV_FILTER, LeAdvertisingFilter);
+  SET_HANDLER(OpCode::LE_ENERGY_INFO, LeEnergyInfo);
+  SET_HANDLER(OpCode::LE_EXTENDED_SCAN_PARAMS, LeExtendedScanParams);
+  SET_HANDLER(OpCode::LE_READ_REMOTE_FEATURES, LeReadRemoteFeatures);
+  SET_HANDLER(OpCode::READ_REMOTE_VERSION_INFORMATION,
+              ReadRemoteVersionInformation);
+  SET_HANDLER(OpCode::LE_CONNECTION_UPDATE, LeConnectionUpdate);
+  SET_HANDLER(OpCode::LE_START_ENCRYPTION, LeStartEncryption);
   SET_HANDLER(OpCode::LE_ADD_DEVICE_TO_RESOLVING_LIST,
-              HciLeAddDeviceToResolvingList);
+              LeAddDeviceToResolvingList);
   SET_HANDLER(OpCode::LE_REMOVE_DEVICE_FROM_RESOLVING_LIST,
-              HciLeRemoveDeviceFromResolvingList);
-  SET_HANDLER(OpCode::LE_CLEAR_RESOLVING_LIST, HciLeClearResolvingList);
-  SET_HANDLER(OpCode::LE_SET_PRIVACY_MODE, HciLeSetPrivacyMode);
+              LeRemoveDeviceFromResolvingList);
+  SET_HANDLER(OpCode::LE_CLEAR_RESOLVING_LIST, LeClearResolvingList);
+  SET_HANDLER(OpCode::LE_SET_PRIVACY_MODE, LeSetPrivacyMode);
   // Testing Commands
-  SET_HANDLER(OpCode::READ_LOOPBACK_MODE, HciReadLoopbackMode);
-  SET_HANDLER(OpCode::WRITE_LOOPBACK_MODE, HciWriteLoopbackMode);
+  SET_HANDLER(OpCode::READ_LOOPBACK_MODE, ReadLoopbackMode);
+  SET_HANDLER(OpCode::WRITE_LOOPBACK_MODE, WriteLoopbackMode);
 #undef SET_HANDLER
 }
 
-void DualModeController::HciSniffSubrating(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 8, "%s size=%zu", __func__, args.size());
+void DualModeController::SniffSubrating(CommandPacketView command) {
+  auto command_view = gd_hci::SniffSubratingView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  uint16_t handle = args.begin().extract<uint16_t>();
-
-  auto packet = bluetooth::hci::SniffSubratingCompleteBuilder::Create(
-      kNumCommandPackets, ErrorCode::SUCCESS, handle);
-  send_event_(std::move(packet));
+  send_event_(gd_hci::SniffSubratingCompleteBuilder::Create(
+      kNumCommandPackets, ErrorCode::SUCCESS,
+      command_view.GetConnectionHandle()));
 }
 
 void DualModeController::RegisterTaskScheduler(
@@ -242,9 +248,8 @@
     cp.connection_handle_ = handle;
     cp.host_num_of_completed_packets_ = kNumCommandPackets;
     completed_packets.push_back(cp);
-    auto packet = bluetooth::hci::NumberOfCompletedPacketsBuilder::Create(
-        completed_packets);
-    send_event_(std::move(packet));
+    send_event_(bluetooth::hci::NumberOfCompletedPacketsBuilder::Create(
+        completed_packets));
     return;
   }
 
@@ -262,9 +267,8 @@
     cp.connection_handle_ = handle;
     cp.host_num_of_completed_packets_ = kNumCommandPackets;
     completed_packets.push_back(cp);
-    auto packet = bluetooth::hci::NumberOfCompletedPacketsBuilder::Create(
-        completed_packets);
-    send_event_(std::move(packet));
+    send_event_(bluetooth::hci::NumberOfCompletedPacketsBuilder::Create(
+        completed_packets));
     return;
   }
 }
@@ -279,7 +283,6 @@
   auto command_packet = bluetooth::hci::CommandPacketView::Create(raw_packet);
   ASSERT(command_packet.IsValid());
   auto op = command_packet.GetOpCode();
-  uint16_t opcode = static_cast<uint16_t>(op);
 
   if (loopback_mode_ == LoopbackMode::ENABLE_LOCAL &&
       // Loopback exceptions.
@@ -290,14 +293,14 @@
       op != OpCode::READ_BUFFER_SIZE && op != OpCode::READ_LOOPBACK_MODE &&
       op != OpCode::WRITE_LOOPBACK_MODE) {
     std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
-        std::make_unique<bluetooth::packet::RawBuilder>();
+        std::make_unique<bluetooth::packet::RawBuilder>(255);
     raw_builder_ptr->AddOctets(*packet);
-    auto packet = bluetooth::hci::LoopbackCommandBuilder::Create(
-        std::move(raw_builder_ptr));
-    send_event_(std::move(packet));
-  } else if (active_hci_commands_.count(opcode) > 0) {
-    active_hci_commands_[opcode](command_packet.GetPayload());
+    send_event_(bluetooth::hci::LoopbackCommandBuilder::Create(
+        std::move(raw_builder_ptr)));
+  } else if (active_hci_commands_.count(op) > 0) {
+    active_hci_commands_[op](command_packet);
   } else {
+    uint16_t opcode = static_cast<uint16_t>(op);
     SendCommandCompleteUnknownOpCodeEvent(opcode);
     LOG_INFO("Unknown command, opcode: 0x%04X, OGF: 0x%04X, OCF: 0x%04X",
              opcode, (opcode & 0xFC00) >> 10, opcode & 0x03FF);
@@ -343,8 +346,9 @@
   send_iso_ = callback;
 }
 
-void DualModeController::HciReset(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::Reset(CommandPacketView command) {
+  auto command_view = gd_hci::ResetView::Create(command);
+  ASSERT(command_view.IsValid());
   link_layer_controller_.Reset();
   if (loopback_mode_ == LoopbackMode::ENABLE_LOCAL) {
     loopback_mode_ = LoopbackMode::NO_LOOPBACK;
@@ -354,8 +358,9 @@
                                                            ErrorCode::SUCCESS));
 }
 
-void DualModeController::HciReadBufferSize(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::ReadBufferSize(CommandPacketView command) {
+  auto command_view = gd_hci::ReadBufferSizeView::Create(command);
+  ASSERT(command_view.IsValid());
 
   auto packet = bluetooth::hci::ReadBufferSizeCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS,
@@ -366,26 +371,29 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciReadEncryptionKeySize(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
-
-  uint16_t handle = args.begin().extract<uint16_t>();
+void DualModeController::ReadEncryptionKeySize(CommandPacketView command) {
+  auto command_view = gd_hci::ReadEncryptionKeySizeView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
   auto packet = bluetooth::hci::ReadEncryptionKeySizeCompleteBuilder::Create(
-      kNumCommandPackets, ErrorCode::SUCCESS, handle,
-      properties_.GetEncryptionKeySize());
+      kNumCommandPackets, ErrorCode::SUCCESS,
+      command_view.GetConnectionHandle(), properties_.GetEncryptionKeySize());
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciHostBufferSize(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 7, "%s  size=%zu", __func__, args.size());
+void DualModeController::HostBufferSize(CommandPacketView command) {
+  auto command_view = gd_hci::HostBufferSizeView::Create(command);
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::HostBufferSizeCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciReadLocalVersionInformation(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::ReadLocalVersionInformation(
+    CommandPacketView command) {
+  auto command_view = gd_hci::ReadLocalVersionInformationView::Create(command);
+  ASSERT(command_view.IsValid());
 
   bluetooth::hci::LocalVersionInformation local_version_information;
   local_version_information.hci_version_ =
@@ -402,14 +410,15 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciReadRemoteVersionInformation(
-    PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
-
-  uint16_t handle = args.begin().extract<uint16_t>();
+void DualModeController::ReadRemoteVersionInformation(
+    CommandPacketView command) {
+  auto command_view = gd_hci::ReadRemoteVersionInformationView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
   auto status = link_layer_controller_.SendCommandToRemoteByHandle(
-      OpCode::READ_REMOTE_VERSION_INFORMATION, args, handle);
+      OpCode::READ_REMOTE_VERSION_INFORMATION, command.GetPayload(),
+      command_view.GetConnectionHandle());
 
   auto packet =
       bluetooth::hci::ReadRemoteVersionInformationStatusBuilder::Create(
@@ -417,15 +426,17 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciReadBdAddr(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::ReadBdAddr(CommandPacketView command) {
+  auto command_view = gd_hci::ReadBdAddrView::Create(command);
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::ReadBdAddrCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS, properties_.GetAddress());
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciReadLocalSupportedCommands(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::ReadLocalSupportedCommands(CommandPacketView command) {
+  auto command_view = gd_hci::ReadLocalSupportedCommandsView::Create(command);
+  ASSERT(command_view.IsValid());
 
   std::array<uint8_t, 64> supported_commands;
   supported_commands.fill(0x00);
@@ -442,8 +453,9 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciReadLocalSupportedFeatures(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::ReadLocalSupportedFeatures(CommandPacketView command) {
+  auto command_view = gd_hci::ReadLocalSupportedFeaturesView::Create(command);
+  ASSERT(command_view.IsValid());
   auto packet =
       bluetooth::hci::ReadLocalSupportedFeaturesCompleteBuilder::Create(
           kNumCommandPackets, ErrorCode::SUCCESS,
@@ -451,17 +463,19 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciReadLocalSupportedCodecs(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::ReadLocalSupportedCodecs(CommandPacketView command) {
+  auto command_view = gd_hci::ReadLocalSupportedCodecsView::Create(command);
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::ReadLocalSupportedCodecsCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS, properties_.GetSupportedCodecs(),
       properties_.GetVendorSpecificCodecs());
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciReadLocalExtendedFeatures(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 1, "%s  size=%zu", __func__, args.size());
-  uint8_t page_number = args.begin().extract<uint8_t>();
+void DualModeController::ReadLocalExtendedFeatures(CommandPacketView command) {
+  auto command_view = gd_hci::ReadLocalExtendedFeaturesView::Create(command);
+  ASSERT(command_view.IsValid());
+  uint8_t page_number = command_view.GetPageNumber();
 
   auto pakcet =
       bluetooth::hci::ReadLocalExtendedFeaturesCompleteBuilder::Create(
@@ -471,39 +485,42 @@
   send_event_(std::move(pakcet));
 }
 
-void DualModeController::HciReadRemoteExtendedFeatures(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 3, "%s  size=%zu", __func__, args.size());
-
-  uint16_t handle = args.begin().extract<uint16_t>();
+void DualModeController::ReadRemoteExtendedFeatures(CommandPacketView command) {
+  auto command_view = gd_hci::ReadRemoteExtendedFeaturesView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
   auto status = link_layer_controller_.SendCommandToRemoteByHandle(
-      OpCode::READ_REMOTE_EXTENDED_FEATURES, args, handle);
+      OpCode::READ_REMOTE_EXTENDED_FEATURES, command_view.GetPayload(),
+      command_view.GetConnectionHandle());
 
   auto packet = bluetooth::hci::ReadRemoteExtendedFeaturesStatusBuilder::Create(
       status, kNumCommandPackets);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciSwitchRole(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 7, "%s  size=%zu", __func__, args.size());
+void DualModeController::SwitchRole(CommandPacketView command) {
+  auto command_view = gd_hci::SwitchRoleView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  Address address = args.begin().extract<Address>();
-  uint8_t role = args.begin().extract<uint8_t>();
-
-  auto status = link_layer_controller_.SwitchRole(address, role);
+  auto status = link_layer_controller_.SwitchRole(
+      command_view.GetBdAddr(), static_cast<uint8_t>(command_view.GetRole()));
 
   auto packet = bluetooth::hci::SwitchRoleStatusBuilder::Create(
       status, kNumCommandPackets);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciReadRemoteSupportedFeatures(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
-
-  uint16_t handle = args.begin().extract<uint16_t>();
+void DualModeController::ReadRemoteSupportedFeatures(
+    CommandPacketView command) {
+  auto command_view = gd_hci::ReadRemoteSupportedFeaturesView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
   auto status = link_layer_controller_.SendCommandToRemoteByHandle(
-      OpCode::READ_REMOTE_SUPPORTED_FEATURES, args, handle);
+      OpCode::READ_REMOTE_SUPPORTED_FEATURES, command_view.GetPayload(),
+      command_view.GetConnectionHandle());
 
   auto packet =
       bluetooth::hci::ReadRemoteSupportedFeaturesStatusBuilder::Create(
@@ -511,27 +528,32 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciReadClockOffset(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
+void DualModeController::ReadClockOffset(CommandPacketView command) {
+  auto command_view = gd_hci::ReadClockOffsetView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  uint16_t handle = args.begin().extract<uint16_t>();
+  uint16_t handle = command_view.GetConnectionHandle();
 
   auto status = link_layer_controller_.SendCommandToRemoteByHandle(
-      OpCode::READ_CLOCK_OFFSET, args, handle);
+      OpCode::READ_CLOCK_OFFSET, command_view.GetPayload(), handle);
 
   auto packet = bluetooth::hci::ReadClockOffsetStatusBuilder::Create(
       status, kNumCommandPackets);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciIoCapabilityRequestReply(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 9, "%s  size=%zu", __func__, args.size());
+void DualModeController::IoCapabilityRequestReply(CommandPacketView command) {
+  auto command_view = gd_hci::IoCapabilityRequestReplyView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto args_itr = args.begin();
-  Address peer = args_itr.extract<Address>();
-  uint8_t io_capability = args_itr.extract<uint8_t>();
-  uint8_t oob_data_present_flag = args_itr.extract<uint8_t>();
-  uint8_t authentication_requirements = args_itr.extract<uint8_t>();
+  Address peer = command_view.GetBdAddr();
+  uint8_t io_capability = static_cast<uint8_t>(command_view.GetIoCapability());
+  uint8_t oob_data_present_flag =
+      static_cast<uint8_t>(command_view.GetOobPresent());
+  uint8_t authentication_requirements =
+      static_cast<uint8_t>(command_view.GetAuthenticationRequirements());
 
   auto status = link_layer_controller_.IoCapabilityRequestReply(
       peer, io_capability, oob_data_present_flag, authentication_requirements);
@@ -541,11 +563,13 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciUserConfirmationRequestReply(
-    PacketView<true> args) {
-  ASSERT_LOG(args.size() == 6, "%s  size=%zu", __func__, args.size());
+void DualModeController::UserConfirmationRequestReply(
+    CommandPacketView command) {
+  auto command_view = gd_hci::UserConfirmationRequestReplyView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  Address peer = args.begin().extract<Address>();
+  Address peer = command_view.GetBdAddr();
 
   auto status = link_layer_controller_.UserConfirmationRequestReply(peer);
   auto packet =
@@ -555,11 +579,13 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciUserConfirmationRequestNegativeReply(
-    PacketView<true> args) {
-  ASSERT_LOG(args.size() == 6, "%s  size=%zu", __func__, args.size());
+void DualModeController::UserConfirmationRequestNegativeReply(
+    CommandPacketView command) {
+  auto command_view = gd_hci::UserConfirmationRequestNegativeReplyView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  Address peer = args.begin().extract<Address>();
+  Address peer = command_view.GetBdAddr();
 
   auto status =
       link_layer_controller_.UserConfirmationRequestNegativeReply(peer);
@@ -570,12 +596,13 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciUserPasskeyRequestReply(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 10, "%s  size=%zu", __func__, args.size());
+void DualModeController::UserPasskeyRequestReply(CommandPacketView command) {
+  auto command_view = gd_hci::UserPasskeyRequestReplyView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto args_itr = args.begin();
-  Address peer = args_itr.extract<Address>();
-  uint32_t numeric_value = args_itr.extract<uint32_t>();
+  Address peer = command_view.GetBdAddr();
+  uint32_t numeric_value = command_view.GetNumericValue();
 
   auto status =
       link_layer_controller_.UserPasskeyRequestReply(peer, numeric_value);
@@ -585,11 +612,13 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciUserPasskeyRequestNegativeReply(
-    PacketView<true> args) {
-  ASSERT_LOG(args.size() == 6, "%s  size=%zu", __func__, args.size());
+void DualModeController::UserPasskeyRequestNegativeReply(
+    CommandPacketView command) {
+  auto command_view = gd_hci::UserPasskeyRequestNegativeReplyView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  Address peer = args.begin().extract<Address>();
+  Address peer = command_view.GetBdAddr();
 
   auto status = link_layer_controller_.UserPasskeyRequestNegativeReply(peer);
   auto packet =
@@ -599,20 +628,18 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciRemoteOobDataRequestReply(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 38, "%s  size=%zu", __func__, args.size());
+void DualModeController::RemoteOobDataRequestReply(CommandPacketView command) {
+  auto command_view = gd_hci::RemoteOobDataRequestReplyView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto args_itr = args.begin();
-  Address peer = args_itr.extract<Address>();
-  std::vector<uint8_t> c;
-  std::vector<uint8_t> r;
-  for (size_t i = 0; i < 16; i++) {
-    c.push_back(args_itr.extract<uint8_t>());
-  }
-  for (size_t i = 0; i < 16; i++) {
-    r.push_back(args_itr.extract<uint8_t>());
-  }
-  auto status = link_layer_controller_.RemoteOobDataRequestReply(peer, c, r);
+  Address peer = command_view.GetBdAddr();
+  std::array<uint8_t, 16> c = command_view.GetC();
+  std::array<uint8_t, 16> r = command_view.GetR();
+
+  auto status = link_layer_controller_.RemoteOobDataRequestReply(
+      peer, std::vector<uint8_t>(c.begin(), c.end()),
+      std::vector<uint8_t>(r.begin(), r.end()));
   auto packet =
       bluetooth::hci::RemoteOobDataRequestReplyCompleteBuilder::Create(
           kNumCommandPackets, status, peer);
@@ -620,11 +647,13 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciRemoteOobDataRequestNegativeReply(
-    PacketView<true> args) {
-  ASSERT_LOG(args.size() == 6, "%s  size=%zu", __func__, args.size());
+void DualModeController::RemoteOobDataRequestNegativeReply(
+    CommandPacketView command) {
+  auto command_view = gd_hci::RemoteOobDataRequestNegativeReplyView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  Address peer = args.begin().extract<Address>();
+  Address peer = command_view.GetBdAddr();
 
   auto status = link_layer_controller_.RemoteOobDataRequestNegativeReply(peer);
   auto packet =
@@ -634,13 +663,14 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciIoCapabilityRequestNegativeReply(
-    PacketView<true> args) {
-  ASSERT_LOG(args.size() == 7, "%s  size=%zu", __func__, args.size());
+void DualModeController::IoCapabilityRequestNegativeReply(
+    CommandPacketView command) {
+  auto command_view = gd_hci::IoCapabilityRequestNegativeReplyView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto args_itr = args.begin();
-  Address peer = args_itr.extract<Address>();
-  ErrorCode reason = args_itr.extract<ErrorCode>();
+  Address peer = command_view.GetBdAddr();
+  ErrorCode reason = command_view.GetReason();
 
   auto status =
       link_layer_controller_.IoCapabilityRequestNegativeReply(peer, reason);
@@ -651,20 +681,25 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteSimplePairingMode(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 1, "%s  size=%zu", __func__, args.size());
-  ASSERT(args[0] == 1 || args[0] == 0);
-  link_layer_controller_.WriteSimplePairingMode(args[0] == 1);
+void DualModeController::WriteSimplePairingMode(CommandPacketView command) {
+  auto command_view = gd_hci::WriteSimplePairingModeView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+
+  link_layer_controller_.WriteSimplePairingMode(
+      command_view.GetSimplePairingMode() == gd_hci::Enable::ENABLED);
   auto packet = bluetooth::hci::WriteSimplePairingModeCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciChangeConnectionPacketType(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 4, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
-  uint16_t packet_type = args_itr.extract<uint16_t>();
+void DualModeController::ChangeConnectionPacketType(CommandPacketView command) {
+  auto command_view = gd_hci::ChangeConnectionPacketTypeView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+
+  uint16_t handle = command_view.GetConnectionHandle();
+  uint16_t packet_type = static_cast<uint16_t>(command_view.GetPacketType());
 
   auto status =
       link_layer_controller_.ChangeConnectionPacketType(handle, packet_type);
@@ -674,16 +709,18 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteLeHostSupport(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
+void DualModeController::WriteLeHostSupport(CommandPacketView command) {
+  auto command_view = gd_hci::WriteLeHostSupportView::Create(command);
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::WriteLeHostSupportCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteSecureConnectionsHostSupport(
-    PacketView<true> args) {
-  ASSERT_LOG(args.size() == 1, "%s  size=%zu", __func__, args.size());
+void DualModeController::WriteSecureConnectionsHostSupport(
+    CommandPacketView command) {
+  auto command_view = gd_hci::WriteSecureConnectionsHostSupportView::Create(
+      gd_hci::SecurityCommandView::Create(command));
   properties_.SetExtendedFeatures(properties_.GetExtendedFeatures(1) | 0x8, 1);
   auto packet =
       bluetooth::hci::WriteSecureConnectionsHostSupportCompleteBuilder::Create(
@@ -691,38 +728,48 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciSetEventMask(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 8, "%s  size=%zu", __func__, args.size());
+void DualModeController::SetEventMask(CommandPacketView command) {
+  auto command_view = gd_hci::SetEventMaskView::Create(command);
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::SetEventMaskCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteInquiryMode(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 1, "%s  size=%zu", __func__, args.size());
-  link_layer_controller_.SetInquiryMode(args[0]);
+void DualModeController::WriteInquiryMode(CommandPacketView command) {
+  auto command_view = gd_hci::WriteInquiryModeView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  link_layer_controller_.SetInquiryMode(
+      static_cast<uint8_t>(command_view.GetInquiryMode()));
   auto packet = bluetooth::hci::WriteInquiryModeCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWritePageScanType(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 1, "%s  size=%zu", __func__, args.size());
+void DualModeController::WritePageScanType(CommandPacketView command) {
+  auto command_view = gd_hci::WritePageScanTypeView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::WritePageScanTypeCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteInquiryScanType(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 1, "%s  size=%zu", __func__, args.size());
+void DualModeController::WriteInquiryScanType(CommandPacketView command) {
+  auto command_view = gd_hci::WriteInquiryScanTypeView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::WriteInquiryScanTypeCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciAuthenticationRequested(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
-  uint16_t handle = args.begin().extract<uint16_t>();
+void DualModeController::AuthenticationRequested(CommandPacketView command) {
+  auto command_view = gd_hci::AuthenticationRequestedView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  uint16_t handle = command_view.GetConnectionHandle();
   auto status = link_layer_controller_.AuthenticationRequested(handle);
 
   auto packet = bluetooth::hci::AuthenticationRequestedStatusBuilder::Create(
@@ -730,11 +777,13 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciSetConnectionEncryption(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 3, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
-  uint8_t encryption_enable = args_itr.extract<uint8_t>();
+void DualModeController::SetConnectionEncryption(CommandPacketView command) {
+  auto command_view = gd_hci::SetConnectionEncryptionView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  uint16_t handle = command_view.GetConnectionHandle();
+  uint8_t encryption_enable =
+      static_cast<uint8_t>(command_view.GetEncryptionEnable());
   auto status =
       link_layer_controller_.SetConnectionEncryption(handle, encryption_enable);
 
@@ -743,10 +792,11 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciChangeConnectionLinkKey(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
+void DualModeController::ChangeConnectionLinkKey(CommandPacketView command) {
+  auto command_view = gd_hci::ChangeConnectionLinkKeyView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  uint16_t handle = command_view.GetConnectionHandle();
 
   auto status = link_layer_controller_.ChangeConnectionLinkKey(handle);
 
@@ -755,10 +805,11 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciMasterLinkKey(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 1, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
-  uint8_t key_flag = args_itr.extract<uint8_t>();
+void DualModeController::MasterLinkKey(CommandPacketView command) {
+  auto command_view = gd_hci::MasterLinkKeyView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  uint8_t key_flag = static_cast<uint8_t>(command_view.GetKeyFlag());
 
   auto status = link_layer_controller_.MasterLinkKey(key_flag);
 
@@ -767,17 +818,21 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteAuthenticationEnable(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 1, "%s  size=%zu", __func__, args.size());
-  properties_.SetAuthenticationEnable(args[0]);
+void DualModeController::WriteAuthenticationEnable(CommandPacketView command) {
+  auto command_view = gd_hci::WriteAuthenticationEnableView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  properties_.SetAuthenticationEnable(
+      static_cast<uint8_t>(command_view.GetAuthenticationEnable()));
   auto packet =
       bluetooth::hci::WriteAuthenticationEnableCompleteBuilder::Create(
           kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciReadAuthenticationEnable(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::ReadAuthenticationEnable(CommandPacketView command) {
+  auto command_view = gd_hci::ReadAuthenticationEnableView::Create(command);
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::ReadAuthenticationEnableCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS,
       static_cast<bluetooth::hci::AuthenticationEnable>(
@@ -785,27 +840,34 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteClassOfDevice(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 3, "%s  size=%zu", __func__, args.size());
-  properties_.SetClassOfDevice(args[0], args[1], args[2]);
+void DualModeController::WriteClassOfDevice(CommandPacketView command) {
+  auto command_view = gd_hci::WriteClassOfDeviceView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  ClassOfDevice class_of_device = command_view.GetClassOfDevice();
+  properties_.SetClassOfDevice(class_of_device.cod[0], class_of_device.cod[1],
+                               class_of_device.cod[2]);
   auto packet = bluetooth::hci::WriteClassOfDeviceCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWritePageTimeout(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
+void DualModeController::WritePageTimeout(CommandPacketView command) {
+  auto command_view = gd_hci::WritePageTimeoutView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::WritePageTimeoutCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciHoldMode(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 6, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
-  uint16_t hold_mode_max_interval = args_itr.extract<uint16_t>();
-  uint16_t hold_mode_min_interval = args_itr.extract<uint16_t>();
+void DualModeController::HoldMode(CommandPacketView command) {
+  auto command_view = gd_hci::HoldModeView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  uint16_t handle = command_view.GetConnectionHandle();
+  uint16_t hold_mode_max_interval = command_view.GetHoldModeMaxInterval();
+  uint16_t hold_mode_min_interval = command_view.GetHoldModeMinInterval();
 
   auto status = link_layer_controller_.HoldMode(handle, hold_mode_max_interval,
                                                 hold_mode_min_interval);
@@ -815,14 +877,15 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciSniffMode(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 10, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
-  uint16_t sniff_max_interval = args_itr.extract<uint16_t>();
-  uint16_t sniff_min_interval = args_itr.extract<uint16_t>();
-  uint16_t sniff_attempt = args_itr.extract<uint16_t>();
-  uint16_t sniff_timeout = args_itr.extract<uint16_t>();
+void DualModeController::SniffMode(CommandPacketView command) {
+  auto command_view = gd_hci::SniffModeView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  uint16_t handle = command_view.GetConnectionHandle();
+  uint16_t sniff_max_interval = command_view.GetSniffMaxInterval();
+  uint16_t sniff_min_interval = command_view.GetSniffMinInterval();
+  uint16_t sniff_attempt = command_view.GetSniffAttempt();
+  uint16_t sniff_timeout = command_view.GetSniffTimeout();
 
   auto status = link_layer_controller_.SniffMode(handle, sniff_max_interval,
                                                  sniff_min_interval,
@@ -833,28 +896,29 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciExitSniffMode(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
+void DualModeController::ExitSniffMode(CommandPacketView command) {
+  auto command_view = gd_hci::ExitSniffModeView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto status = link_layer_controller_.ExitSniffMode(handle);
+  auto status =
+      link_layer_controller_.ExitSniffMode(command_view.GetConnectionHandle());
 
   auto packet = bluetooth::hci::ExitSniffModeStatusBuilder::Create(
       status, kNumCommandPackets);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciQosSetup(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 20, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
-  args_itr.extract<uint8_t>();  // unused
-  uint8_t service_type = args_itr.extract<uint8_t>();
-  uint32_t token_rate = args_itr.extract<uint32_t>();
-  uint32_t peak_bandwidth = args_itr.extract<uint32_t>();
-  uint32_t latency = args_itr.extract<uint32_t>();
-  uint32_t delay_variation = args_itr.extract<uint32_t>();
+void DualModeController::QosSetup(CommandPacketView command) {
+  auto command_view = gd_hci::QosSetupView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  uint16_t handle = command_view.GetConnectionHandle();
+  uint8_t service_type = static_cast<uint8_t>(command_view.GetServiceType());
+  uint32_t token_rate = command_view.GetTokenRate();
+  uint32_t peak_bandwidth = command_view.GetPeakBandwidth();
+  uint32_t latency = command_view.GetLatency();
+  uint32_t delay_variation = command_view.GetDelayVariation();
 
   auto status =
       link_layer_controller_.QosSetup(handle, service_type, token_rate,
@@ -865,26 +929,29 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteDefaultLinkPolicySettings(
-    PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
+void DualModeController::WriteDefaultLinkPolicySettings(
+    CommandPacketView command) {
+  auto command_view = gd_hci::WriteDefaultLinkPolicySettingsView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   auto packet =
       bluetooth::hci::WriteDefaultLinkPolicySettingsCompleteBuilder::Create(
           kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciFlowSpecification(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 21, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
-  args_itr.extract<uint8_t>();  // unused
-  uint8_t flow_direction = args_itr.extract<uint8_t>();
-  uint8_t service_type = args_itr.extract<uint8_t>();
-  uint32_t token_rate = args_itr.extract<uint32_t>();
-  uint32_t token_bucket_size = args_itr.extract<uint32_t>();
-  uint32_t peak_bandwidth = args_itr.extract<uint32_t>();
-  uint32_t access_latency = args_itr.extract<uint32_t>();
+void DualModeController::FlowSpecification(CommandPacketView command) {
+  auto command_view = gd_hci::FlowSpecificationView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  uint16_t handle = command_view.GetConnectionHandle();
+  uint8_t flow_direction =
+      static_cast<uint8_t>(command_view.GetFlowDirection());
+  uint8_t service_type = static_cast<uint8_t>(command_view.GetServiceType());
+  uint32_t token_rate = command_view.GetTokenRate();
+  uint32_t token_bucket_size = command_view.GetTokenBucketSize();
+  uint32_t peak_bandwidth = command_view.GetPeakBandwidth();
+  uint32_t access_latency = command_view.GetAccessLatency();
 
   auto status = link_layer_controller_.FlowSpecification(
       handle, flow_direction, service_type, token_rate, token_bucket_size,
@@ -895,12 +962,13 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteLinkPolicySettings(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 4, "%s  size=%zu", __func__, args.size());
+void DualModeController::WriteLinkPolicySettings(CommandPacketView command) {
+  auto command_view = gd_hci::WriteLinkPolicySettingsView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
-  uint16_t settings = args_itr.extract<uint16_t>();
+  uint16_t handle = command_view.GetConnectionHandle();
+  uint16_t settings = command_view.GetLinkPolicySettings();
 
   auto status =
       link_layer_controller_.WriteLinkPolicySettings(handle, settings);
@@ -910,12 +978,14 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteLinkSupervisionTimeout(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 4, "%s  size=%zu", __func__, args.size());
+void DualModeController::WriteLinkSupervisionTimeout(
+    CommandPacketView command) {
+  auto command_view = gd_hci::WriteLinkSupervisionTimeoutView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
-  uint16_t timeout = args_itr.extract<uint16_t>();
+  uint16_t handle = command_view.GetHandle();
+  uint16_t timeout = command_view.GetLinkSupervisionTimeout();
 
   auto status =
       link_layer_controller_.WriteLinkSupervisionTimeout(handle, timeout);
@@ -925,8 +995,9 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciReadLocalName(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::ReadLocalName(CommandPacketView command) {
+  auto command_view = gd_hci::ReadLocalNameView::Create(command);
+  ASSERT(command_view.IsValid());
 
   std::array<uint8_t, 248> local_name;
   local_name.fill(0x00);
@@ -941,31 +1012,33 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteLocalName(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 248, "%s  size=%zu", __func__, args.size());
-  std::vector<uint8_t> clipped(args.begin(), args.begin() + LastNonZero(args) + 1);
-  properties_.SetName(clipped);
+void DualModeController::WriteLocalName(CommandPacketView command) {
+  auto command_view = gd_hci::WriteLocalNameView::Create(command);
+  ASSERT(command_view.IsValid());
+  properties_.SetName(std::vector<uint8_t>(command_view.GetLocalName().begin(),
+                                           command_view.GetLocalName().end()));
   auto packet = bluetooth::hci::WriteLocalNameCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteExtendedInquiryResponse(
-    PacketView<true> args) {
-  ASSERT_LOG(args.size() == 241, "%s  size=%zu", __func__, args.size());
-  // Strip FEC byte and trailing zeros
-  std::vector<uint8_t> clipped(args.begin() + 1, args.begin() + LastNonZero(args) + 1);
-  properties_.SetExtendedInquiryData(clipped);
+void DualModeController::WriteExtendedInquiryResponse(
+    CommandPacketView command) {
+  auto command_view = gd_hci::WriteExtendedInquiryResponseView::Create(command);
+  ASSERT(command_view.IsValid());
+  properties_.SetExtendedInquiryData(std::vector<uint8_t>(
+      command_view.GetPayload().begin() + 1, command_view.GetPayload().end()));
   auto packet =
       bluetooth::hci::WriteExtendedInquiryResponseCompleteBuilder::Create(
           kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciRefreshEncryptionKey(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
+void DualModeController::RefreshEncryptionKey(CommandPacketView command) {
+  auto command_view = gd_hci::RefreshEncryptionKeyView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  uint16_t handle = command_view.GetConnectionHandle();
   auto status_packet =
       bluetooth::hci::RefreshEncryptionKeyStatusBuilder::Create(
           ErrorCode::SUCCESS, kNumCommandPackets);
@@ -977,67 +1050,88 @@
   send_event_(std::move(complete_packet));
 }
 
-void DualModeController::HciWriteVoiceSetting(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
+void DualModeController::WriteVoiceSetting(CommandPacketView command) {
+  auto command_view = gd_hci::WriteVoiceSettingView::Create(command);
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::WriteVoiceSettingCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteCurrentIacLap(PacketView<true> args) {
-  ASSERT(args.size() > 0);
-  ASSERT(args.size() == 1 + (3 * args[0]));  // count + 3-byte IACs
+void DualModeController::WriteCurrentIacLap(CommandPacketView command) {
+  auto command_view = gd_hci::WriteCurrentIacLapView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::WriteCurrentIacLapCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteInquiryScanActivity(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 4, "%s  size=%zu", __func__, args.size());
+void DualModeController::WriteInquiryScanActivity(CommandPacketView command) {
+  auto command_view = gd_hci::WriteInquiryScanActivityView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::WriteInquiryScanActivityCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteScanEnable(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 1, "%s  size=%zu", __func__, args.size());
-  link_layer_controller_.SetInquiryScanEnable(args[0] & 0x1);
-  link_layer_controller_.SetPageScanEnable(args[0] & 0x2);
+void DualModeController::WriteScanEnable(CommandPacketView command) {
+  auto command_view = gd_hci::WriteScanEnableView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  link_layer_controller_.SetInquiryScanEnable(
+      command_view.GetScanEnable() ==
+          gd_hci::ScanEnable::INQUIRY_AND_PAGE_SCAN ||
+      command_view.GetScanEnable() == gd_hci::ScanEnable::INQUIRY_SCAN_ONLY);
+  link_layer_controller_.SetPageScanEnable(
+      command_view.GetScanEnable() ==
+          gd_hci::ScanEnable::INQUIRY_AND_PAGE_SCAN ||
+      command_view.GetScanEnable() == gd_hci::ScanEnable::PAGE_SCAN_ONLY);
   auto packet = bluetooth::hci::WriteScanEnableCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciSetEventFilter(PacketView<true> args) {
-  ASSERT(args.size() > 0);
+void DualModeController::SetEventFilter(CommandPacketView command) {
+  auto command_view = gd_hci::SetEventFilterView::Create(command);
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::SetEventFilterCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciInquiry(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 5, "%s  size=%zu", __func__, args.size());
-  link_layer_controller_.SetInquiryLAP(args[0] | (args[1], 8) | (args[2], 16));
-  link_layer_controller_.SetInquiryMaxResponses(args[4]);
-  link_layer_controller_.StartInquiry(std::chrono::milliseconds(args[3] * 1280));
+void DualModeController::Inquiry(CommandPacketView command) {
+  auto command_view = gd_hci::InquiryView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  link_layer_controller_.SetInquiryLAP(command_view.GetLap().lap_);
+  link_layer_controller_.SetInquiryMaxResponses(command_view.GetNumResponses());
+  link_layer_controller_.StartInquiry(
+      std::chrono::milliseconds(command_view.GetInquiryLength() * 1280));
 
   auto packet = bluetooth::hci::InquiryStatusBuilder::Create(
       ErrorCode::SUCCESS, kNumCommandPackets);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciInquiryCancel(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::InquiryCancel(CommandPacketView command) {
+  auto command_view = gd_hci::InquiryCancelView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   link_layer_controller_.InquiryCancel();
   auto packet = bluetooth::hci::InquiryCancelCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciAcceptConnectionRequest(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 7, "%s  size=%zu", __func__, args.size());
-  Address addr = args.begin().extract<Address>();
-  bool try_role_switch = args[6] == 0;
+void DualModeController::AcceptConnectionRequest(CommandPacketView command) {
+  auto command_view = gd_hci::AcceptConnectionRequestView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  Address addr = command_view.GetBdAddr();
+  bool try_role_switch = command_view.GetRole() ==
+                         gd_hci::AcceptConnectionRequestRole::BECOME_MASTER;
   auto status =
       link_layer_controller_.AcceptConnectionRequest(addr, try_role_switch);
   auto packet = bluetooth::hci::AcceptConnectionRequestStatusBuilder::Create(
@@ -1045,31 +1139,36 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciRejectConnectionRequest(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 7, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
-  Address addr = args_itr.extract<Address>();
-  uint8_t reason = args_itr.extract<uint8_t>();
+void DualModeController::RejectConnectionRequest(CommandPacketView command) {
+  auto command_view = gd_hci::RejectConnectionRequestView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  Address addr = command_view.GetBdAddr();
+  uint8_t reason = static_cast<uint8_t>(command_view.GetReason());
   auto status = link_layer_controller_.RejectConnectionRequest(addr, reason);
   auto packet = bluetooth::hci::RejectConnectionRequestStatusBuilder::Create(
       status, kNumCommandPackets);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLinkKeyRequestReply(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 22, "%s  size=%zu", __func__, args.size());
-  auto args_it = args.begin();
-  Address addr = args_it.extract<Address>();
-  auto key = args.begin().extract<std::array<uint8_t, 16>>();
+void DualModeController::LinkKeyRequestReply(CommandPacketView command) {
+  auto command_view = gd_hci::LinkKeyRequestReplyView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  Address addr = command_view.GetBdAddr();
+  auto key = command_view.GetLinkKey();
   auto status = link_layer_controller_.LinkKeyRequestReply(addr, key);
   auto packet = bluetooth::hci::LinkKeyRequestReplyCompleteBuilder::Create(
       kNumCommandPackets, status);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLinkKeyRequestNegativeReply(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 6, "%s  size=%zu", __func__, args.size());
-  Address addr = args.begin().extract<Address>();
+void DualModeController::LinkKeyRequestNegativeReply(
+    CommandPacketView command) {
+  auto command_view = gd_hci::LinkKeyRequestNegativeReplyView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  Address addr = command_view.GetBdAddr();
   auto status = link_layer_controller_.LinkKeyRequestNegativeReply(addr);
   auto packet =
       bluetooth::hci::LinkKeyRequestNegativeReplyCompleteBuilder::Create(
@@ -1077,17 +1176,20 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciDeleteStoredLinkKey(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 7, "%s  size=%zu", __func__, args.size());
+void DualModeController::DeleteStoredLinkKey(CommandPacketView command) {
+  auto command_view = gd_hci::DeleteStoredLinkKeyView::Create(
+      gd_hci::SecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
   uint16_t deleted_keys = 0;
 
-  if (args[6] == 0) {
-    Address addr = args.begin().extract<Address>();
+  auto flag = command_view.GetDeleteAllFlag();
+  if (flag == gd_hci::DeleteStoredLinkKeyDeleteAllFlag::SPECIFIED_BD_ADDR) {
+    Address addr = command_view.GetBdAddr();
     deleted_keys = security_manager_.DeleteKey(addr);
   }
 
-  if (args[6] == 1) {
+  if (flag == gd_hci::DeleteStoredLinkKeyDeleteAllFlag::ALL) {
     security_manager_.DeleteAllKeys();
   }
 
@@ -1097,32 +1199,36 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciRemoteNameRequest(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 10, "%s  size=%zu", __func__, args.size());
+void DualModeController::RemoteNameRequest(CommandPacketView command) {
+  auto command_view = gd_hci::RemoteNameRequestView::Create(
+      gd_hci::DiscoveryCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  Address remote_addr = args.begin().extract<Address>();
+  Address remote_addr = command_view.GetBdAddr();
 
   auto status = link_layer_controller_.SendCommandToRemoteByAddress(
-      OpCode::REMOTE_NAME_REQUEST, args, remote_addr);
+      OpCode::REMOTE_NAME_REQUEST, command_view.GetPayload(), remote_addr);
 
   auto packet = bluetooth::hci::RemoteNameRequestStatusBuilder::Create(
       status, kNumCommandPackets);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeSetEventMask(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 8, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeSetEventMask(CommandPacketView command) {
+  auto command_view = gd_hci::LeSetEventMaskView::Create(command);
+  ASSERT(command_view.IsValid());
   /*
-    uint64_t mask = args.begin().extract<uint64_t>();
-    link_layer_controller_.SetLeEventMask(mask);
-  */
+  uint64_t mask = args.begin().extract<uint64_t>();
+  link_layer_controller_.SetLeEventMask(mask);
+*/
   auto packet = bluetooth::hci::LeSetEventMaskCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeReadBufferSize(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeReadBufferSize(CommandPacketView command) {
+  auto command_view = gd_hci::LeReadBufferSizeView::Create(command);
+  ASSERT(command_view.IsValid());
 
   bluetooth::hci::LeBufferSize le_buffer_size;
   le_buffer_size.le_data_packet_length_ = properties_.GetLeDataPacketLength();
@@ -1133,9 +1239,10 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeReadLocalSupportedFeatures(
-    PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeReadLocalSupportedFeatures(
+    CommandPacketView command) {
+  auto command_view = gd_hci::LeReadLocalSupportedFeaturesView::Create(command);
+  ASSERT(command_view.IsValid());
   auto packet =
       bluetooth::hci::LeReadLocalSupportedFeaturesCompleteBuilder::Create(
           kNumCommandPackets, ErrorCode::SUCCESS,
@@ -1143,24 +1250,27 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeSetRandomAddress(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 6, "%s  size=%zu", __func__, args.size());
-  properties_.SetLeAddress(args.begin().extract<Address>());
+void DualModeController::LeSetRandomAddress(CommandPacketView command) {
+  auto command_view = gd_hci::LeSetRandomAddressView::Create(
+      gd_hci::LeAdvertisingCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  properties_.SetLeAddress(command_view.GetRandomAddress());
   auto packet = bluetooth::hci::LeSetRandomAddressCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeSetAdvertisingParameters(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 15, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
+void DualModeController::LeSetAdvertisingParameters(CommandPacketView command) {
+  auto command_view = gd_hci::LeSetAdvertisingParametersView::Create(
+      gd_hci::LeAdvertisingCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   properties_.SetLeAdvertisingParameters(
-      args_itr.extract<uint16_t>() /* AdverisingIntervalMin */,
-      args_itr.extract<uint16_t>() /* AdverisingIntervalMax */, args_itr.extract<uint8_t>() /* AdverisingType */,
-      args_itr.extract<uint8_t>() /* OwnAddressType */, args_itr.extract<uint8_t>() /* PeerAddressType */,
-      args_itr.extract<Address>() /* PeerAddress */, args_itr.extract<uint8_t>() /* AdvertisingChannelMap */,
-      args_itr.extract<uint8_t>() /* AdvertisingFilterPolicy */
-  );
+      command_view.GetIntervalMin(), command_view.GetIntervalMax(),
+      static_cast<uint8_t>(command_view.GetType()),
+      static_cast<uint8_t>(command_view.GetOwnAddressType()),
+      static_cast<uint8_t>(command_view.GetPeerAddressType()),
+      command_view.GetPeerAddress(), command_view.GetChannelMap(),
+      static_cast<uint8_t>(command_view.GetFilterPolicy()));
 
   auto packet =
       bluetooth::hci::LeSetAdvertisingParametersCompleteBuilder::Create(
@@ -1168,73 +1278,104 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeSetAdvertisingData(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 32, "%s  size=%zu", __func__, args.size());
-  properties_.SetLeAdvertisement(std::vector<uint8_t>(args.begin() + 1, args.end()));
+void DualModeController::LeSetAdvertisingData(CommandPacketView command) {
+  auto command_view = gd_hci::LeSetAdvertisingDataView::Create(
+      gd_hci::LeAdvertisingCommandView::Create(command));
+  auto payload = command.GetPayload();
+  std::vector<uint8_t> payload_bytes{payload.begin() + 1,
+                                     payload.begin() + *payload.begin()};
+  ASSERT_LOG(command_view.IsValid(), "%s command.size() = %zu",
+             gd_hci::OpCodeText(command.GetOpCode()).c_str(), command.size());
+  ASSERT(command_view.GetPayload().size() == 32);
+  properties_.SetLeAdvertisement(payload_bytes);
   auto packet = bluetooth::hci::LeSetAdvertisingDataCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeSetScanResponseData(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 32, "%s  size=%zu", __func__, args.size());
-  properties_.SetLeScanResponse(std::vector<uint8_t>(args.begin() + 1, args.end()));
+void DualModeController::LeSetScanResponseData(CommandPacketView command) {
+  auto command_view = gd_hci::LeSetScanResponseDataView::Create(
+      gd_hci::LeAdvertisingCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  ASSERT(command_view.GetPayload().size() == 32);
+  properties_.SetLeScanResponse(std::vector<uint8_t>(
+      command_view.GetPayload().begin() + 1, command_view.GetPayload().end()));
   auto packet = bluetooth::hci::LeSetScanResponseDataCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeSetAdvertisingEnable(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 1, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeSetAdvertisingEnable(CommandPacketView command) {
+  auto command_view = gd_hci::LeSetAdvertisingEnableView::Create(
+      gd_hci::LeAdvertisingCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   auto status = link_layer_controller_.SetLeAdvertisingEnable(
-      args.begin().extract<uint8_t>());
+      command_view.GetAdvertisingEnable() == gd_hci::Enable::ENABLED);
   auto packet = bluetooth::hci::LeSetAdvertisingEnableCompleteBuilder::Create(
       kNumCommandPackets, status);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeSetScanParameters(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 7, "%s  size=%zu", __func__, args.size());
-  link_layer_controller_.SetLeScanType(args[0]);
-  link_layer_controller_.SetLeScanInterval(args[1] | (args[2], 8));
-  link_layer_controller_.SetLeScanWindow(args[3] | (args[4], 8));
-  link_layer_controller_.SetLeAddressType(args[5]);
-  link_layer_controller_.SetLeScanFilterPolicy(args[6]);
+void DualModeController::LeSetScanParameters(CommandPacketView command) {
+  auto command_view = gd_hci::LeSetScanParametersView::Create(
+      gd_hci::LeScanningCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  link_layer_controller_.SetLeScanType(
+      static_cast<uint8_t>(command_view.GetLeScanType()));
+  link_layer_controller_.SetLeScanInterval(command_view.GetLeScanInterval());
+  link_layer_controller_.SetLeScanWindow(command_view.GetLeScanWindow());
+  link_layer_controller_.SetLeAddressType(
+      static_cast<uint8_t>(command_view.GetOwnAddressType()));
+  link_layer_controller_.SetLeScanFilterPolicy(
+      static_cast<uint8_t>(command_view.GetScanningFilterPolicy()));
   auto packet = bluetooth::hci::LeSetScanParametersCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeSetScanEnable(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
-  link_layer_controller_.SetLeScanEnable(args[0]);
-  link_layer_controller_.SetLeFilterDuplicates(args[1]);
+void DualModeController::LeSetScanEnable(CommandPacketView command) {
+  auto command_view = gd_hci::LeSetScanEnableView::Create(
+      gd_hci::LeScanningCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  link_layer_controller_.SetLeScanEnable(command_view.GetLeScanEnable() ==
+                                         gd_hci::Enable::ENABLED);
+  link_layer_controller_.SetLeFilterDuplicates(
+      command_view.GetFilterDuplicates() == gd_hci::Enable::ENABLED);
   auto packet = bluetooth::hci::LeSetScanEnableCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeCreateConnection(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 25, "%s  size=%zu", __func__, args.size());
-  auto args_itr = args.begin();
-  link_layer_controller_.SetLeScanInterval(args_itr.extract<uint16_t>());
-  link_layer_controller_.SetLeScanWindow(args_itr.extract<uint16_t>());
-  uint8_t initiator_filter_policy = args_itr.extract<uint8_t>();
+void DualModeController::LeCreateConnection(CommandPacketView command) {
+  auto command_view = gd_hci::LeCreateConnectionView::Create(
+      gd_hci::LeConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
+  link_layer_controller_.SetLeScanInterval(command_view.GetLeScanInterval());
+  link_layer_controller_.SetLeScanWindow(command_view.GetLeScanWindow());
+  uint8_t initiator_filter_policy =
+      static_cast<uint8_t>(command_view.GetInitiatorFilterPolicy());
   link_layer_controller_.SetLeInitiatorFilterPolicy(initiator_filter_policy);
 
   if (initiator_filter_policy == 0) {  // White list not used
-    uint8_t peer_address_type = args_itr.extract<uint8_t>();
-    Address peer_address = args_itr.extract<Address>();
+    uint8_t peer_address_type =
+        static_cast<uint8_t>(command_view.GetPeerAddressType());
+    Address peer_address = command_view.GetPeerAddress();
     link_layer_controller_.SetLePeerAddressType(peer_address_type);
     link_layer_controller_.SetLePeerAddress(peer_address);
   }
-  link_layer_controller_.SetLeAddressType(args_itr.extract<uint8_t>());
-  link_layer_controller_.SetLeConnectionIntervalMin(args_itr.extract<uint16_t>());
-  link_layer_controller_.SetLeConnectionIntervalMax(args_itr.extract<uint16_t>());
-  link_layer_controller_.SetLeConnectionLatency(args_itr.extract<uint16_t>());
-  link_layer_controller_.SetLeSupervisionTimeout(args_itr.extract<uint16_t>());
-  link_layer_controller_.SetLeMinimumCeLength(args_itr.extract<uint16_t>());
-  link_layer_controller_.SetLeMaximumCeLength(args_itr.extract<uint16_t>());
+  link_layer_controller_.SetLeAddressType(
+      static_cast<uint8_t>(command_view.GetOwnAddressType()));
+  link_layer_controller_.SetLeConnectionIntervalMin(
+      command_view.GetConnIntervalMin());
+  link_layer_controller_.SetLeConnectionIntervalMax(
+      command_view.GetConnIntervalMax());
+  link_layer_controller_.SetLeConnectionLatency(command_view.GetConnLatency());
+  link_layer_controller_.SetLeSupervisionTimeout(
+      command_view.GetSupervisionTimeout());
+  link_layer_controller_.SetLeMinimumCeLength(
+      command_view.GetMinimumCeLength());
+  link_layer_controller_.SetLeMaximumCeLength(
+      command_view.GetMaximumCeLength());
 
   auto status = link_layer_controller_.SetLeConnect(true);
 
@@ -1243,8 +1384,10 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeConnectionUpdate(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 14, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeConnectionUpdate(CommandPacketView command) {
+  auto command_view = gd_hci::LeConnectionUpdateView::Create(
+      gd_hci::LeConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
   auto status_packet = bluetooth::hci::LeConnectionUpdateStatusBuilder::Create(
       ErrorCode::CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR, kNumCommandPackets);
@@ -1256,15 +1399,21 @@
   send_event_(std::move(complete_packet));
 }
 
-void DualModeController::HciCreateConnection(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 13, "%s  size=%zu", __func__, args.size());
+void DualModeController::CreateConnection(CommandPacketView command) {
+  auto command_view = gd_hci::CreateConnectionView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto args_itr = args.begin();
-  Address address = args_itr.extract<Address>();
-  uint16_t packet_type = args_itr.extract<uint16_t>();
-  uint8_t page_scan_mode = args_itr.extract<uint8_t>();
-  uint16_t clock_offset = args_itr.extract<uint16_t>();
-  uint8_t allow_role_switch = args_itr.extract<uint8_t>();
+  Address address = command_view.GetBdAddr();
+  uint16_t packet_type = command_view.GetPacketType();
+  uint8_t page_scan_mode =
+      static_cast<uint8_t>(command_view.GetPageScanRepetitionMode());
+  uint16_t clock_offset =
+      (command_view.GetClockOffsetValid() == gd_hci::ClockOffsetValid::VALID
+           ? command_view.GetClockOffset()
+           : 0);
+  uint8_t allow_role_switch =
+      static_cast<uint8_t>(command_view.GetAllowRoleSwitch());
 
   auto status = link_layer_controller_.CreateConnection(
       address, packet_type, page_scan_mode, clock_offset, allow_role_switch);
@@ -1274,12 +1423,13 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciDisconnect(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 3, "%s  size=%zu", __func__, args.size());
+void DualModeController::Disconnect(CommandPacketView command) {
+  auto command_view = gd_hci::DisconnectView::Create(
+      gd_hci::ConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
-  uint8_t reason = args_itr.extract<uint8_t>();
+  uint16_t handle = command_view.GetConnectionHandle();
+  uint8_t reason = static_cast<uint8_t>(command_view.GetReason());
 
   auto status = link_layer_controller_.Disconnect(handle, reason);
 
@@ -1288,8 +1438,10 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeConnectionCancel(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeConnectionCancel(CommandPacketView command) {
+  auto command_view = gd_hci::LeCreateConnectionCancelView::Create(
+      gd_hci::LeConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   link_layer_controller_.SetLeConnect(false);
   auto packet = bluetooth::hci::LeCreateConnectionCancelStatusBuilder::Create(
       ErrorCode::SUCCESS, kNumCommandPackets);
@@ -1302,23 +1454,29 @@
   */
 }
 
-void DualModeController::HciLeReadWhiteListSize(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeReadWhiteListSize(CommandPacketView command) {
+  auto command_view = gd_hci::LeReadWhiteListSizeView::Create(
+      gd_hci::LeConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::LeReadWhiteListSizeCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS, properties_.GetLeWhiteListSize());
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeClearWhiteList(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeClearWhiteList(CommandPacketView command) {
+  auto command_view = gd_hci::LeClearWhiteListView::Create(
+      gd_hci::LeConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   link_layer_controller_.LeWhiteListClear();
   auto packet = bluetooth::hci::LeClearWhiteListCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeAddDeviceToWhiteList(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 7, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeAddDeviceToWhiteList(CommandPacketView command) {
+  auto command_view = gd_hci::LeAddDeviceToWhiteListView::Create(
+      gd_hci::LeConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
   if (link_layer_controller_.LeWhiteListFull()) {
     auto packet = bluetooth::hci::LeAddDeviceToWhiteListCompleteBuilder::Create(
@@ -1326,21 +1484,22 @@
     send_event_(std::move(packet));
     return;
   }
-  auto args_itr = args.begin();
-  uint8_t addr_type = args_itr.extract<uint8_t>();
-  Address address = args_itr.extract<Address>();
+  uint8_t addr_type = static_cast<uint8_t>(command_view.GetAddressType());
+  Address address = command_view.GetAddress();
   link_layer_controller_.LeWhiteListAddDevice(address, addr_type);
   auto packet = bluetooth::hci::LeAddDeviceToWhiteListCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeRemoveDeviceFromWhiteList(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 7, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeRemoveDeviceFromWhiteList(
+    CommandPacketView command) {
+  auto command_view = gd_hci::LeRemoveDeviceFromWhiteListView::Create(
+      gd_hci::LeConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto args_itr = args.begin();
-  uint8_t addr_type = args_itr.extract<uint8_t>();
-  Address address = args_itr.extract<Address>();
+  uint8_t addr_type = static_cast<uint8_t>(command_view.GetAddressType());
+  Address address = command_view.GetAddress();
   link_layer_controller_.LeWhiteListRemoveDevice(address, addr_type);
   auto packet =
       bluetooth::hci::LeRemoveDeviceFromWhiteListCompleteBuilder::Create(
@@ -1348,16 +1507,20 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeClearResolvingList(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeClearResolvingList(CommandPacketView command) {
+  auto command_view = gd_hci::LeClearResolvingListView::Create(
+      gd_hci::LeSecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   link_layer_controller_.LeResolvingListClear();
   auto packet = bluetooth::hci::LeClearResolvingListCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeAddDeviceToResolvingList(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 39, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeAddDeviceToResolvingList(CommandPacketView command) {
+  auto command_view = gd_hci::LeAddDeviceToResolvingListView::Create(
+      gd_hci::LeSecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
   if (link_layer_controller_.LeResolvingListFull()) {
     auto packet =
@@ -1366,20 +1529,13 @@
     send_event_(std::move(packet));
     return;
   }
-  auto args_itr = args.begin();
-  uint8_t addr_type = args_itr.extract<uint8_t>();
-  Address address = args_itr.extract<Address>();
-  std::array<uint8_t, LinkLayerController::kIrk_size> peerIrk;
-  std::array<uint8_t, LinkLayerController::kIrk_size> localIrk;
-  for (size_t irk_ind = 0; irk_ind < LinkLayerController::kIrk_size;
-       irk_ind++) {
-    peerIrk[irk_ind] = args_itr.extract<uint8_t>();
-  }
-
-  for (size_t irk_ind = 0; irk_ind < LinkLayerController::kIrk_size;
-       irk_ind++) {
-    localIrk[irk_ind] = args_itr.extract<uint8_t>();
-  }
+  uint8_t addr_type =
+      static_cast<uint8_t>(command_view.GetPeerIdentityAddressType());
+  Address address = command_view.GetPeerIdentityAddress();
+  std::array<uint8_t, LinkLayerController::kIrk_size> peerIrk =
+      command_view.GetPeerIrk();
+  std::array<uint8_t, LinkLayerController::kIrk_size> localIrk =
+      command_view.GetLocalIrk();
 
   link_layer_controller_.LeResolvingListAddDevice(address, addr_type, peerIrk,
                                                   localIrk);
@@ -1389,13 +1545,15 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeRemoveDeviceFromResolvingList(
-    PacketView<true> args) {
-  ASSERT_LOG(args.size() == 7, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeRemoveDeviceFromResolvingList(
+    CommandPacketView command) {
+  auto command_view = gd_hci::LeRemoveDeviceFromResolvingListView::Create(
+      gd_hci::LeSecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto args_itr = args.begin();
-  uint8_t addr_type = args_itr.extract<uint8_t>();
-  Address address = args_itr.extract<Address>();
+  uint8_t addr_type =
+      static_cast<uint8_t>(command_view.GetPeerIdentityAddressType());
+  Address address = command_view.GetPeerIdentityAddress();
   link_layer_controller_.LeResolvingListRemoveDevice(address, addr_type);
   auto packet =
       bluetooth::hci::LeRemoveDeviceFromResolvingListCompleteBuilder::Create(
@@ -1403,13 +1561,15 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeSetPrivacyMode(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 8, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeSetPrivacyMode(CommandPacketView command) {
+  auto command_view = gd_hci::LeSetPrivacyModeView::Create(
+      gd_hci::LeSecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto args_itr = args.begin();
-  uint8_t peer_identity_address_type = args_itr.extract<uint8_t>();
-  Address peer_identity_address = args_itr.extract<Address>();
-  uint8_t privacy_mode = args_itr.extract<uint8_t>();
+  uint8_t peer_identity_address_type =
+      static_cast<uint8_t>(command_view.GetPeerIdentityAddressType());
+  Address peer_identity_address = command_view.GetPeerIdentityAddress();
+  uint8_t privacy_mode = static_cast<uint8_t>(command_view.GetPrivacyMode());
 
   if (link_layer_controller_.LeResolvingListContainsDevice(
           peer_identity_address, peer_identity_address_type)) {
@@ -1422,21 +1582,25 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeReadRemoteFeatures(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 2, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeReadRemoteFeatures(CommandPacketView command) {
+  auto command_view = gd_hci::LeReadRemoteFeaturesView::Create(
+      gd_hci::LeConnectionManagementCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  uint16_t handle = args.begin().extract<uint16_t>();
+  uint16_t handle = command_view.GetConnectionHandle();
 
   auto status = link_layer_controller_.SendCommandToRemoteByHandle(
-      OpCode::LE_READ_REMOTE_FEATURES, args, handle);
+      OpCode::LE_READ_REMOTE_FEATURES, command_view.GetPayload(), handle);
 
   auto packet = bluetooth::hci::LeConnectionUpdateStatusBuilder::Create(
       status, kNumCommandPackets);
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeRand(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeRand(CommandPacketView command) {
+  auto command_view = gd_hci::LeRandView::Create(
+      gd_hci::LeSecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   uint64_t random_val = 0;
   for (size_t rand_bytes = 0; rand_bytes < sizeof(uint64_t); rand_bytes += sizeof(RAND_MAX)) {
     random_val = (random_val << (8 * sizeof(RAND_MAX))) | random();
@@ -1447,16 +1611,19 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeReadSupportedStates(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeReadSupportedStates(CommandPacketView command) {
+  auto command_view = gd_hci::LeReadSupportedStatesView::Create(command);
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::LeReadSupportedStatesCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS,
       properties_.GetLeSupportedStates());
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeVendorCap(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeVendorCap(CommandPacketView command) {
+  auto command_view = gd_hci::LeGetVendorCapabilitiesView::Create(
+      gd_hci::VendorCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   vector<uint8_t> caps = properties_.GetLeVendorCap();
   if (caps.size() == 0) {
     SendCommandCompleteUnknownOpCodeEvent(
@@ -1475,41 +1642,45 @@
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciLeVendorMultiAdv(PacketView<true> args) {
-  ASSERT(args.size() > 0);
+void DualModeController::LeVendorMultiAdv(CommandPacketView command) {
+  auto command_view = gd_hci::LeMultiAdvtView::Create(
+      gd_hci::LeAdvertisingCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   SendCommandCompleteUnknownOpCodeEvent(
       static_cast<uint16_t>(OpCode::LE_MULTI_ADVT));
 }
 
-void DualModeController::HciLeAdvertisingFilter(PacketView<true> args) {
-  ASSERT(args.size() > 0);
+void DualModeController::LeAdvertisingFilter(CommandPacketView command) {
+  auto command_view = gd_hci::LeAdvFilterView::Create(
+      gd_hci::LeScanningCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   SendCommandCompleteUnknownOpCodeEvent(
       static_cast<uint16_t>(OpCode::LE_ADV_FILTER));
 }
 
-void DualModeController::HciLeEnergyInfo(PacketView<true> args) {
-  ASSERT(args.size() > 0);
+void DualModeController::LeEnergyInfo(CommandPacketView command) {
+  auto command_view = gd_hci::LeEnergyInfoView::Create(
+      gd_hci::VendorCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   SendCommandCompleteUnknownOpCodeEvent(
       static_cast<uint16_t>(OpCode::LE_ENERGY_INFO));
 }
 
-void DualModeController::HciLeExtendedScanParams(PacketView<true> args) {
-  ASSERT(args.size() > 0);
+void DualModeController::LeExtendedScanParams(CommandPacketView command) {
+  auto command_view = gd_hci::LeExtendedScanParamsView::Create(
+      gd_hci::LeScanningCommandView::Create(command));
+  ASSERT(command_view.IsValid());
   SendCommandCompleteUnknownOpCodeEvent(
       static_cast<uint16_t>(OpCode::LE_EXTENDED_SCAN_PARAMS));
 }
 
-void DualModeController::HciLeStartEncryption(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 28, "%s  size=%zu", __func__, args.size());
+void DualModeController::LeStartEncryption(CommandPacketView command) {
+  auto command_view = gd_hci::LeStartEncryptionView::Create(
+      gd_hci::LeSecurityCommandView::Create(command));
+  ASSERT(command_view.IsValid());
 
-  auto args_itr = args.begin();
-  uint16_t handle = args_itr.extract<uint16_t>();
-  // uint64_t random_number = args_itr.extract<uint64_t>();
-  // uint16_t encrypted_diversifier = args_itr.extract<uint16_t>();
-  // std::vector<uint8_t> long_term_key;
-  // for (size_t i = 0; i < 16; i++) {
-  //   long_term_key.push_back(args_itr.extract<uint18_t>();
-  // }
+  uint16_t handle = command_view.GetConnectionHandle();
+
   auto status_packet = bluetooth::hci::LeStartEncryptionStatusBuilder::Create(
       ErrorCode::SUCCESS, kNumCommandPackets);
   send_event_(std::move(status_packet));
@@ -1517,71 +1688,21 @@
   auto complete_packet = bluetooth::hci::EncryptionChangeBuilder::Create(
       ErrorCode::SUCCESS, handle, bluetooth::hci::EncryptionEnabled::OFF);
   send_event_(std::move(complete_packet));
-#if 0
-
-  std::shared_ptr<packets::AclPacketBuilder> encryption_information =
-      std::make_shared<packets::AclPacketBuilder>(
-          0x0002, Acl::FIRST_AUTOMATICALLY_FLUSHABLE, Acl::POINT_TO_POINT,
-          std::vector<uint8_t>({}));
-
-  encryption_information->AddPayloadOctets2(0x0011);
-  encryption_information->AddPayloadOctets2(0x0006);
-  encryption_information->AddPayloadOctets1(0x06);
-  encryption_information->AddPayloadOctets8(0x0706050403020100);
-  encryption_information->AddPayloadOctets8(0x0F0E0D0C0B0A0908);
-
-  send_acl_(encryption_information);
-
-  encryption_information = std::make_shared<packets::AclPacketBuilder>(
-      0x0002, Acl::FIRST_AUTOMATICALLY_FLUSHABLE, Acl::POINT_TO_POINT,
-      std::vector<uint8_t>({}));
-
-  encryption_information->AddPayloadOctets2(0x000B);
-  encryption_information->AddPayloadOctets2(0x0006);
-  encryption_information->AddPayloadOctets1(0x07);
-  encryption_information->AddPayloadOctets2(0xBEEF);
-  encryption_information->AddPayloadOctets8(0x0706050403020100);
-
-  send_acl_(encryption_information);
-
-  encryption_information = std::make_shared<packets::AclPacketBuilder>(
-      0x0002, Acl::FIRST_AUTOMATICALLY_FLUSHABLE, Acl::POINT_TO_POINT,
-      std::vector<uint8_t>({}));
-
-  encryption_information->AddPayloadOctets2(0x0011);
-  encryption_information->AddPayloadOctets2(0x0006);
-  encryption_information->AddPayloadOctets1(0x08);
-  encryption_information->AddPayloadOctets8(0x0F0E0D0C0B0A0908);
-  encryption_information->AddPayloadOctets8(0x0706050403020100);
-
-  send_acl_(encryption_information);
-
-  encryption_information = std::make_shared<packets::AclPacketBuilder>(
-      0x0002, Acl::FIRST_AUTOMATICALLY_FLUSHABLE, Acl::POINT_TO_POINT,
-      std::vector<uint8_t>({}));
-
-  encryption_information->AddPayloadOctets2(0x0008);
-  encryption_information->AddPayloadOctets2(0x0006);
-  encryption_information->AddPayloadOctets1(0x09);
-  encryption_information->AddPayloadOctets1(0x01);
-  encryption_information->AddPayloadOctets6(0xDEADBEEFF00D);
-  send_acl_(encryption_information);
-  // send_event_(packets::EventPacketBuilder::CreateLeStartEncryption()->ToVector());
-
-#endif
 }
 
-void DualModeController::HciReadLoopbackMode(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 0, "%s size=%zu", __func__, args.size());
+void DualModeController::ReadLoopbackMode(CommandPacketView command) {
+  auto command_view = gd_hci::ReadLoopbackModeView::Create(command);
+  ASSERT(command_view.IsValid());
   auto packet = bluetooth::hci::ReadLoopbackModeCompleteBuilder::Create(
       kNumCommandPackets, ErrorCode::SUCCESS,
       static_cast<LoopbackMode>(loopback_mode_));
   send_event_(std::move(packet));
 }
 
-void DualModeController::HciWriteLoopbackMode(PacketView<true> args) {
-  ASSERT_LOG(args.size() == 1, "%s size=%zu", __func__, args.size());
-  loopback_mode_ = static_cast<LoopbackMode>(args[0]);
+void DualModeController::WriteLoopbackMode(CommandPacketView command) {
+  auto command_view = gd_hci::WriteLoopbackModeView::Create(command);
+  ASSERT(command_view.IsValid());
+  loopback_mode_ = command_view.GetLoopbackMode();
   // ACL channel
   uint16_t acl_handle = 0x123;
   auto packet_acl = bluetooth::hci::ConnectionCompleteBuilder::Create(
diff --git a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
index b024cbb..65c2dad 100644
--- a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
+++ b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
@@ -34,7 +34,7 @@
 namespace test_vendor_lib {
 
 using ::bluetooth::hci::Address;
-using ::bluetooth::packet::PacketView;
+using ::bluetooth::hci::CommandPacketView;
 
 // Emulates a dual mode BR/EDR + LE controller by maintaining the link layer
 // state machine detailed in the Bluetooth Core Specification Version 4.2,
@@ -107,315 +107,315 @@
   // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.1
 
   // 7.1.1
-  void HciInquiry(PacketView<true> args);
+  void Inquiry(CommandPacketView args);
 
   // 7.1.2
-  void HciInquiryCancel(PacketView<true> args);
+  void InquiryCancel(CommandPacketView args);
 
   // 7.1.5
-  void HciCreateConnection(PacketView<true> args);
+  void CreateConnection(CommandPacketView args);
 
   // 7.1.6
-  void HciDisconnect(PacketView<true> args);
+  void Disconnect(CommandPacketView args);
 
   // 7.1.8
-  void HciAcceptConnectionRequest(PacketView<true> args);
+  void AcceptConnectionRequest(CommandPacketView args);
 
   // 7.1.9
-  void HciRejectConnectionRequest(PacketView<true> args);
+  void RejectConnectionRequest(CommandPacketView args);
 
   // 7.1.10
-  void HciLinkKeyRequestReply(PacketView<true> args);
+  void LinkKeyRequestReply(CommandPacketView args);
 
   // 7.1.11
-  void HciLinkKeyRequestNegativeReply(PacketView<true> args);
+  void LinkKeyRequestNegativeReply(CommandPacketView args);
 
   // 7.1.14
-  void HciChangeConnectionPacketType(PacketView<true> args);
+  void ChangeConnectionPacketType(CommandPacketView args);
 
   // 7.1.15
-  void HciAuthenticationRequested(PacketView<true> args);
+  void AuthenticationRequested(CommandPacketView args);
 
   // 7.1.16
-  void HciSetConnectionEncryption(PacketView<true> args);
+  void SetConnectionEncryption(CommandPacketView args);
 
   // 7.1.17
-  void HciChangeConnectionLinkKey(PacketView<true> args);
+  void ChangeConnectionLinkKey(CommandPacketView args);
 
   // 7.1.18
-  void HciMasterLinkKey(PacketView<true> args);
+  void MasterLinkKey(CommandPacketView args);
 
   // 7.1.19
-  void HciRemoteNameRequest(PacketView<true> args);
+  void RemoteNameRequest(CommandPacketView args);
 
   // 7.2.8
-  void HciSwitchRole(PacketView<true> args);
+  void SwitchRole(CommandPacketView args);
 
   // 7.1.21
-  void HciReadRemoteSupportedFeatures(PacketView<true> args);
+  void ReadRemoteSupportedFeatures(CommandPacketView args);
 
   // 7.1.22
-  void HciReadRemoteExtendedFeatures(PacketView<true> args);
+  void ReadRemoteExtendedFeatures(CommandPacketView args);
 
   // 7.1.23
-  void HciReadRemoteVersionInformation(PacketView<true> args);
+  void ReadRemoteVersionInformation(CommandPacketView args);
 
   // 7.1.24
-  void HciReadClockOffset(PacketView<true> args);
+  void ReadClockOffset(CommandPacketView args);
 
   // 7.1.29
-  void HciIoCapabilityRequestReply(PacketView<true> args);
+  void IoCapabilityRequestReply(CommandPacketView args);
 
   // 7.1.30
-  void HciUserConfirmationRequestReply(PacketView<true> args);
+  void UserConfirmationRequestReply(CommandPacketView args);
 
   // 7.1.31
-  void HciUserConfirmationRequestNegativeReply(PacketView<true> args);
+  void UserConfirmationRequestNegativeReply(CommandPacketView args);
 
   // 7.1.32
-  void HciUserPasskeyRequestReply(PacketView<true> args);
+  void UserPasskeyRequestReply(CommandPacketView args);
 
   // 7.1.33
-  void HciUserPasskeyRequestNegativeReply(PacketView<true> args);
+  void UserPasskeyRequestNegativeReply(CommandPacketView args);
 
   // 7.1.34
-  void HciRemoteOobDataRequestReply(PacketView<true> args);
+  void RemoteOobDataRequestReply(CommandPacketView args);
 
   // 7.1.35
-  void HciRemoteOobDataRequestNegativeReply(PacketView<true> args);
+  void RemoteOobDataRequestNegativeReply(CommandPacketView args);
 
   // 7.1.36
-  void HciIoCapabilityRequestNegativeReply(PacketView<true> args);
+  void IoCapabilityRequestNegativeReply(CommandPacketView args);
 
   // Link Policy Commands
   // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.2
 
   // 7.2.1
-  void HciHoldMode(PacketView<true> args);
+  void HoldMode(CommandPacketView args);
 
   // 7.2.2
-  void HciSniffMode(PacketView<true> args);
+  void SniffMode(CommandPacketView args);
 
   // 7.2.3
-  void HciExitSniffMode(PacketView<true> args);
+  void ExitSniffMode(CommandPacketView args);
 
   // 7.2.6
-  void HciQosSetup(PacketView<true> args);
+  void QosSetup(CommandPacketView args);
 
   // 7.2.10
-  void HciWriteLinkPolicySettings(PacketView<true> args);
+  void WriteLinkPolicySettings(CommandPacketView args);
 
   // 7.2.12
-  void HciWriteDefaultLinkPolicySettings(PacketView<true> args);
+  void WriteDefaultLinkPolicySettings(CommandPacketView args);
 
   // 7.2.13
-  void HciFlowSpecification(PacketView<true> args);
+  void FlowSpecification(CommandPacketView args);
 
   // 7.2.14
-  void HciSniffSubrating(PacketView<true> args);
+  void SniffSubrating(CommandPacketView args);
 
   // Link Controller Commands
   // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3
 
   // 7.3.1
-  void HciSetEventMask(PacketView<true> args);
+  void SetEventMask(CommandPacketView args);
 
   // 7.3.2
-  void HciReset(PacketView<true> args);
+  void Reset(CommandPacketView args);
 
   // 7.3.3
-  void HciSetEventFilter(PacketView<true> args);
+  void SetEventFilter(CommandPacketView args);
 
   // 7.3.10
-  void HciDeleteStoredLinkKey(PacketView<true> args);
+  void DeleteStoredLinkKey(CommandPacketView args);
 
   // 7.3.11
-  void HciWriteLocalName(PacketView<true> args);
+  void WriteLocalName(CommandPacketView args);
 
   // 7.3.12
-  void HciReadLocalName(PacketView<true> args);
+  void ReadLocalName(CommandPacketView args);
 
   // 7.3.16
-  void HciWritePageTimeout(PacketView<true> args);
+  void WritePageTimeout(CommandPacketView args);
 
   // 7.3.18
-  void HciWriteScanEnable(PacketView<true> args);
+  void WriteScanEnable(CommandPacketView args);
 
   // 7.3.22
-  void HciWriteInquiryScanActivity(PacketView<true> args);
+  void WriteInquiryScanActivity(CommandPacketView args);
 
   // 7.3.23
-  void HciReadAuthenticationEnable(PacketView<true> args);
+  void ReadAuthenticationEnable(CommandPacketView args);
 
   // 7.3.24
-  void HciWriteAuthenticationEnable(PacketView<true> args);
+  void WriteAuthenticationEnable(CommandPacketView args);
 
   // 7.3.26
-  void HciWriteClassOfDevice(PacketView<true> args);
+  void WriteClassOfDevice(CommandPacketView args);
 
   // 7.3.28
-  void HciWriteVoiceSetting(PacketView<true> args);
+  void WriteVoiceSetting(CommandPacketView args);
 
   // 7.3.39
-  void HciHostBufferSize(PacketView<true> args);
+  void HostBufferSize(CommandPacketView args);
 
   // 7.3.42
-  void HciWriteLinkSupervisionTimeout(PacketView<true> args);
+  void WriteLinkSupervisionTimeout(CommandPacketView args);
 
   // 7.3.45
-  void HciWriteCurrentIacLap(PacketView<true> args);
+  void WriteCurrentIacLap(CommandPacketView args);
 
   // 7.3.48
-  void HciWriteInquiryScanType(PacketView<true> args);
+  void WriteInquiryScanType(CommandPacketView args);
 
   // 7.3.50
-  void HciWriteInquiryMode(PacketView<true> args);
+  void WriteInquiryMode(CommandPacketView args);
 
   // 7.3.52
-  void HciWritePageScanType(PacketView<true> args);
+  void WritePageScanType(CommandPacketView args);
 
   // 7.3.56
-  void HciWriteExtendedInquiryResponse(PacketView<true> args);
+  void WriteExtendedInquiryResponse(CommandPacketView args);
 
   // 7.3.57
-  void HciRefreshEncryptionKey(PacketView<true> args);
+  void RefreshEncryptionKey(CommandPacketView args);
 
   // 7.3.59
-  void HciWriteSimplePairingMode(PacketView<true> args);
+  void WriteSimplePairingMode(CommandPacketView args);
 
   // 7.3.79
-  void HciWriteLeHostSupport(PacketView<true> args);
+  void WriteLeHostSupport(CommandPacketView args);
 
   // 7.3.92
-  void HciWriteSecureConnectionsHostSupport(PacketView<true> args);
+  void WriteSecureConnectionsHostSupport(CommandPacketView args);
 
   // Informational Parameters Commands
   // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.4
 
   // 7.4.5
-  void HciReadBufferSize(PacketView<true> args);
+  void ReadBufferSize(CommandPacketView args);
 
   // 7.4.1
-  void HciReadLocalVersionInformation(PacketView<true> args);
+  void ReadLocalVersionInformation(CommandPacketView args);
 
   // 7.4.6
-  void HciReadBdAddr(PacketView<true> args);
+  void ReadBdAddr(CommandPacketView args);
 
   // 7.4.2
-  void HciReadLocalSupportedCommands(PacketView<true> args);
+  void ReadLocalSupportedCommands(CommandPacketView args);
 
   // 7.4.3
-  void HciReadLocalSupportedFeatures(PacketView<true> args);
+  void ReadLocalSupportedFeatures(CommandPacketView args);
 
   // 7.4.4
-  void HciReadLocalExtendedFeatures(PacketView<true> args);
+  void ReadLocalExtendedFeatures(CommandPacketView args);
 
   // 7.4.8
-  void HciReadLocalSupportedCodecs(PacketView<true> args);
+  void ReadLocalSupportedCodecs(CommandPacketView args);
 
   // Status Parameters Commands
   // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.5
 
   // 7.5.7
-  void HciReadEncryptionKeySize(PacketView<true> args);
+  void ReadEncryptionKeySize(CommandPacketView args);
 
   // Test Commands
   // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.7
 
   // 7.7.1
-  void HciReadLoopbackMode(PacketView<true> args);
+  void ReadLoopbackMode(CommandPacketView args);
 
   // 7.7.2
-  void HciWriteLoopbackMode(PacketView<true> args);
+  void WriteLoopbackMode(CommandPacketView args);
 
   // LE Controller Commands
   // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8
 
   // 7.8.1
-  void HciLeSetEventMask(PacketView<true> args);
+  void LeSetEventMask(CommandPacketView args);
 
   // 7.8.2
-  void HciLeReadBufferSize(PacketView<true> args);
+  void LeReadBufferSize(CommandPacketView args);
 
   // 7.8.3
-  void HciLeReadLocalSupportedFeatures(PacketView<true> args);
+  void LeReadLocalSupportedFeatures(CommandPacketView args);
 
   // 7.8.4
-  void HciLeSetRandomAddress(PacketView<true> args);
+  void LeSetRandomAddress(CommandPacketView args);
 
   // 7.8.5
-  void HciLeSetAdvertisingParameters(PacketView<true> args);
+  void LeSetAdvertisingParameters(CommandPacketView args);
 
   // 7.8.7
-  void HciLeSetAdvertisingData(PacketView<true> args);
+  void LeSetAdvertisingData(CommandPacketView args);
 
   // 7.8.8
-  void HciLeSetScanResponseData(PacketView<true> args);
+  void LeSetScanResponseData(CommandPacketView args);
 
   // 7.8.9
-  void HciLeSetAdvertisingEnable(PacketView<true> args);
+  void LeSetAdvertisingEnable(CommandPacketView args);
 
   // 7.8.10
-  void HciLeSetScanParameters(PacketView<true> args);
+  void LeSetScanParameters(CommandPacketView args);
 
   // 7.8.11
-  void HciLeSetScanEnable(PacketView<true> args);
+  void LeSetScanEnable(CommandPacketView args);
 
   // 7.8.12
-  void HciLeCreateConnection(PacketView<true> args);
+  void LeCreateConnection(CommandPacketView args);
 
   // 7.8.18
-  void HciLeConnectionUpdate(PacketView<true> args);
+  void LeConnectionUpdate(CommandPacketView args);
 
   // 7.8.13
-  void HciLeConnectionCancel(PacketView<true> args);
+  void LeConnectionCancel(CommandPacketView args);
 
   // 7.8.14
-  void HciLeReadWhiteListSize(PacketView<true> args);
+  void LeReadWhiteListSize(CommandPacketView args);
 
   // 7.8.15
-  void HciLeClearWhiteList(PacketView<true> args);
+  void LeClearWhiteList(CommandPacketView args);
 
   // 7.8.16
-  void HciLeAddDeviceToWhiteList(PacketView<true> args);
+  void LeAddDeviceToWhiteList(CommandPacketView args);
 
   // 7.8.17
-  void HciLeRemoveDeviceFromWhiteList(PacketView<true> args);
+  void LeRemoveDeviceFromWhiteList(CommandPacketView args);
 
   // 7.8.21
-  void HciLeReadRemoteFeatures(PacketView<true> args);
+  void LeReadRemoteFeatures(CommandPacketView args);
 
   // 7.8.23
-  void HciLeRand(PacketView<true> args);
+  void LeRand(CommandPacketView args);
 
   // 7.8.24
-  void HciLeStartEncryption(PacketView<true> args);
+  void LeStartEncryption(CommandPacketView args);
 
   // 7.8.27
-  void HciLeReadSupportedStates(PacketView<true> args);
+  void LeReadSupportedStates(CommandPacketView args);
 
   // 7.8.38
-  void HciLeAddDeviceToResolvingList(PacketView<true> args);
+  void LeAddDeviceToResolvingList(CommandPacketView args);
 
   // 7.8.39
-  void HciLeRemoveDeviceFromResolvingList(PacketView<true> args);
+  void LeRemoveDeviceFromResolvingList(CommandPacketView args);
 
   // 7.8.40
-  void HciLeClearResolvingList(PacketView<true> args);
+  void LeClearResolvingList(CommandPacketView args);
 
   // 7.8.77
-  void HciLeSetPrivacyMode(PacketView<true> args);
+  void LeSetPrivacyMode(CommandPacketView args);
 
   // Vendor-specific Commands
 
-  void HciLeVendorSleepMode(PacketView<true> args);
-  void HciLeVendorCap(PacketView<true> args);
-  void HciLeVendorMultiAdv(PacketView<true> args);
-  void HciLeVendor155(PacketView<true> args);
-  void HciLeVendor157(PacketView<true> args);
-  void HciLeEnergyInfo(PacketView<true> args);
-  void HciLeAdvertisingFilter(PacketView<true> args);
-  void HciLeExtendedScanParams(PacketView<true> args);
+  void LeVendorSleepMode(CommandPacketView args);
+  void LeVendorCap(CommandPacketView args);
+  void LeVendorMultiAdv(CommandPacketView args);
+  void LeVendor155(CommandPacketView args);
+  void LeVendor157(CommandPacketView args);
+  void LeEnergyInfo(CommandPacketView args);
+  void LeAdvertisingFilter(CommandPacketView args);
+  void LeExtendedScanParams(CommandPacketView args);
 
   void SetTimerPeriod(std::chrono::milliseconds new_period);
   void StartTimer();
@@ -443,7 +443,8 @@
   // Maintains the commands to be registered and used in the HciHandler object.
   // Keys are command opcodes and values are the callbacks to handle each
   // command.
-  std::unordered_map<uint16_t, std::function<void(PacketView<true>)>>
+  std::unordered_map<bluetooth::hci::OpCode,
+                     std::function<void(bluetooth::hci::CommandPacketView)>>
       active_hci_commands_;
 
   bluetooth::hci::LoopbackMode loopback_mode_;
diff --git a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
index 8f0975d..2c78ffb 100644
--- a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
+++ b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
@@ -104,8 +104,8 @@
   if (!connections_.HasHandle(handle)) {
     return ErrorCode::UNKNOWN_CONNECTION;
   }
-  return SendCommandToRemoteByAddress(opcode, args,
-                                      connections_.GetAddress(handle));
+  return SendCommandToRemoteByAddress(
+      opcode, args, connections_.GetAddress(handle).GetAddress());
 }
 
 ErrorCode LinkLayerController::SendAclToRemote(
@@ -115,11 +115,9 @@
     return ErrorCode::UNKNOWN_CONNECTION;
   }
 
-  Address my_address = properties_.GetAddress();
-  Address destination = connections_.GetAddress(handle);
-  if (connections_.GetOwnAddressType(handle) != 0) {  // If it's not public, it must be LE
-    my_address = properties_.GetLeAddress();
-  }
+  AddressWithType my_address = connections_.GetOwnAddress(handle);
+  AddressWithType destination = connections_.GetAddress(handle);
+  Phy::Type phy = connections_.GetPhyType(handle);
 
   LOG_INFO("%s(%s): handle 0x%x size %d", __func__, properties_.GetAddress().ToString().c_str(), handle,
            static_cast<int>(acl_packet.size()));
@@ -150,9 +148,17 @@
   raw_builder_ptr->AddOctets(payload_bytes);
 
   auto acl = model::packets::AclPacketBuilder::Create(
-      my_address, destination, std::move(raw_builder_ptr));
+      my_address.GetAddress(), destination.GetAddress(),
+      std::move(raw_builder_ptr));
 
-  SendLinkLayerPacket(std::move(acl));
+  switch (phy) {
+    case Phy::Type::BR_EDR:
+      SendLinkLayerPacket(std::move(acl));
+      break;
+    case Phy::Type::LOW_ENERGY:
+      SendLeLinkLayerPacket(std::move(acl));
+      break;
+  }
   return ErrorCode::SUCCESS;
 }
 
@@ -287,15 +293,16 @@
   auto acl_view = bluetooth::hci::AclPacketView::Create(raw_packet);
   ASSERT(acl_view.IsValid());
 
-  LOG_INFO("%s: remote handle 0x%x size %d", __func__, acl_view.GetHandle(), static_cast<int>(acl_view.size()));
-  uint16_t local_handle = connections_.GetHandle(incoming.GetSourceAddress());
+  LOG_INFO("%s: remote handle 0x%x size %d", __func__, acl_view.GetHandle(),
+           static_cast<int>(acl_view.size()));
+  uint16_t local_handle =
+      connections_.GetHandleOnlyAddress(incoming.GetSourceAddress());
   LOG_INFO("%s: local handle 0x%x", __func__, local_handle);
 
-  std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
-      std::make_unique<bluetooth::packet::RawBuilder>();
   std::vector<uint8_t> payload_data(acl_view.GetPayload().begin(),
                                     acl_view.GetPayload().end());
-  raw_builder_ptr->AddOctets(payload_data);
+  std::unique_ptr<bluetooth::packet::RawBuilder> raw_builder_ptr =
+      std::make_unique<bluetooth::packet::RawBuilder>(payload_data);
 
   auto acl_packet = bluetooth::hci::AclPacketBuilder::Create(
       local_handle, acl_view.GetPacketBoundaryFlag(),
@@ -354,15 +361,15 @@
       model::packets::ReadRemoteSupportedFeaturesResponseView::Create(packet);
   ASSERT(view.IsValid());
   Address source = packet.GetSourceAddress();
-  if (connections_.IsDeviceConnected(source)) {
-    uint16_t handle = connections_.GetHandle(source);
-    send_event_(
-        bluetooth::hci::ReadRemoteSupportedFeaturesCompleteBuilder::Create(
-            ErrorCode::SUCCESS, handle, view.GetFeatures()));
-  } else {
+  uint16_t handle = connections_.GetHandleOnlyAddress(source);
+  if (handle == acl::kReservedHandle) {
     LOG_INFO("Discarding response from a disconnected device %s",
              source.ToString().c_str());
+    return;
   }
+  send_event_(
+      bluetooth::hci::ReadRemoteSupportedFeaturesCompleteBuilder::Create(
+          ErrorCode::SUCCESS, handle, view.GetFeatures()));
 }
 
 void LinkLayerController::IncomingReadRemoteExtendedFeatures(
@@ -387,16 +394,16 @@
       model::packets::ReadRemoteExtendedFeaturesResponseView::Create(packet);
   ASSERT(view.IsValid());
   Address source = packet.GetSourceAddress();
-  if (connections_.IsDeviceConnected(source)) {
-    uint16_t handle = connections_.GetHandle(packet.GetSourceAddress());
+  uint16_t handle = connections_.GetHandleOnlyAddress(source);
+  if (handle == acl::kReservedHandle) {
+    LOG_INFO("Discarding response from a disconnected device %s",
+             source.ToString().c_str());
+    return;
+  }
     send_event_(
         bluetooth::hci::ReadRemoteExtendedFeaturesCompleteBuilder::Create(
             static_cast<ErrorCode>(view.GetStatus()), handle,
             view.GetPageNumber(), view.GetMaxPageNumber(), view.GetFeatures()));
-  } else {
-    LOG_INFO("Discarding response from a disconnected device %s",
-             source.ToString().c_str());
-  }
 }
 
 void LinkLayerController::IncomingReadRemoteVersion(
@@ -413,16 +420,16 @@
       model::packets::ReadRemoteVersionInformationResponseView::Create(packet);
   ASSERT(view.IsValid());
   Address source = packet.GetSourceAddress();
-  if (connections_.IsDeviceConnected(source)) {
-    uint16_t handle = connections_.GetHandle(packet.GetSourceAddress());
+  uint16_t handle = connections_.GetHandleOnlyAddress(source);
+  if (handle == acl::kReservedHandle) {
+    LOG_INFO("Discarding response from a disconnected device %s",
+             source.ToString().c_str());
+    return;
+  }
     send_event_(
         bluetooth::hci::ReadRemoteVersionInformationCompleteBuilder::Create(
             ErrorCode::SUCCESS, handle, view.GetLmpVersion(),
             view.GetManufacturerName(), view.GetLmpSubversion()));
-  } else {
-    LOG_INFO("Discarding response from a disconnected device %s",
-             source.ToString().c_str());
-  }
 }
 
 void LinkLayerController::IncomingReadClockOffset(
@@ -437,14 +444,14 @@
   auto view = model::packets::ReadClockOffsetResponseView::Create(packet);
   ASSERT(view.IsValid());
   Address source = packet.GetSourceAddress();
-  if (connections_.IsDeviceConnected(source)) {
-    uint16_t handle = connections_.GetHandle(packet.GetSourceAddress());
-    send_event_(bluetooth::hci::ReadClockOffsetCompleteBuilder::Create(
-        ErrorCode::SUCCESS, handle, view.GetOffset()));
-  } else {
+  uint16_t handle = connections_.GetHandleOnlyAddress(source);
+  if (handle == acl::kReservedHandle) {
     LOG_INFO("Discarding response from a disconnected device %s",
              source.ToString().c_str());
+    return;
   }
+  send_event_(bluetooth::hci::ReadClockOffsetCompleteBuilder::Create(
+      ErrorCode::SUCCESS, handle, view.GetOffset()));
 }
 
 void LinkLayerController::IncomingDisconnectPacket(
@@ -454,9 +461,10 @@
   ASSERT(disconnect.IsValid());
 
   Address peer = incoming.GetSourceAddress();
-  uint16_t handle = connections_.GetHandle(peer);
+  uint16_t handle = connections_.GetHandleOnlyAddress(peer);
   if (handle == acl::kReservedHandle) {
-    LOG_INFO("%s: Unknown connection @%s", __func__, peer.ToString().c_str());
+    LOG_INFO("Discarding disconnect from a disconnected device %s",
+             peer.ToString().c_str());
     return;
   }
   ASSERT_LOG(connections_.Disconnect(handle), "GetHandle() returned invalid handle %hx", handle);
@@ -471,7 +479,7 @@
 
   // TODO: Check keys
   Address peer = incoming.GetSourceAddress();
-  uint16_t handle = connections_.GetHandle(peer);
+  uint16_t handle = connections_.GetHandleOnlyAddress(peer);
   if (handle == acl::kReservedHandle) {
     LOG_INFO("%s: Unknown connection @%s", __func__, peer.ToString().c_str());
     return;
@@ -495,7 +503,8 @@
     model::packets::LinkLayerPacketView incoming) {
   LOG_INFO("%s", __func__);
   // TODO: Check keys
-  uint16_t handle = connections_.GetHandle(incoming.GetSourceAddress());
+  uint16_t handle =
+      connections_.GetHandleOnlyAddress(incoming.GetSourceAddress());
   if (handle == acl::kReservedHandle) {
     LOG_INFO("%s: Unknown connection @%s", __func__, incoming.GetSourceAddress().ToString().c_str());
     return;
@@ -636,7 +645,8 @@
   uint8_t oob_data_present = request.GetOobDataPresent();
   uint8_t authentication_requirements = request.GetAuthenticationRequirements();
 
-  uint16_t handle = connections_.GetHandle(peer);
+  uint16_t handle = connections_.GetHandle(AddressWithType(
+      peer, bluetooth::hci::AddressType::PUBLIC_DEVICE_ADDRESS));
   if (handle == acl::kReservedHandle) {
     LOG_INFO("%s: Device not connected %s", __func__, peer.ToString().c_str());
     return;
@@ -707,8 +717,7 @@
   ASSERT(advertisement.IsValid());
   auto adv_type = static_cast<LeAdvertisement::AdvertisementType>(
       advertisement.GetAdvertisementType());
-  auto address_type =
-      static_cast<LeAdvertisement::AddressType>(advertisement.GetAddressType());
+  auto address_type = advertisement.GetAddressType();
 
   if (le_scan_enable_) {
     vector<uint8_t> ad = advertisement.GetData();
@@ -737,13 +746,19 @@
   }
 
   // Connect
-  if ((le_connect_ && le_peer_address_ == address && le_peer_address_type_ == static_cast<uint8_t>(address_type) &&
+  if ((le_connect_ && le_peer_address_ == address &&
+       le_peer_address_type_ == static_cast<uint8_t>(address_type) &&
        (adv_type == LeAdvertisement::AdvertisementType::ADV_IND ||
         adv_type == LeAdvertisement::AdvertisementType::ADV_DIRECT_IND)) ||
-      (LeWhiteListContainsDevice(address, static_cast<uint8_t>(address_type)))) {
-    if (!connections_.CreatePendingLeConnection(incoming.GetSourceAddress(), static_cast<uint8_t>(address_type))) {
-      LOG_WARN("%s: CreatePendingLeConnection failed for connection to %s (type %hhx)", __func__,
-               incoming.GetSourceAddress().ToString().c_str(), address_type);
+      (LeWhiteListContainsDevice(address,
+                                 static_cast<uint8_t>(address_type)))) {
+    if (!connections_.CreatePendingLeConnection(AddressWithType(
+            address, static_cast<bluetooth::hci::AddressType>(address_type)))) {
+      LOG_WARN(
+          "%s: CreatePendingLeConnection failed for connection to %s (type "
+          "%hhx)",
+          __func__, incoming.GetSourceAddress().ToString().c_str(),
+          address_type);
     }
     LOG_INFO("%s: connecting to %s (type %hhx)", __func__, incoming.GetSourceAddress().ToString().c_str(),
              address_type);
@@ -760,20 +775,23 @@
   }
 }
 
-void LinkLayerController::HandleLeConnection(Address address, uint8_t address_type, uint8_t own_address_type,
-                                             uint8_t role, uint16_t connection_interval, uint16_t connection_latency,
+void LinkLayerController::HandleLeConnection(AddressWithType address,
+                                             AddressWithType own_address,
+                                             uint8_t role,
+                                             uint16_t connection_interval,
+                                             uint16_t connection_latency,
                                              uint16_t supervision_timeout) {
   // TODO: Choose between LeConnectionComplete and LeEnhancedConnectionComplete
-  uint16_t handle = connections_.CreateLeConnection(address, address_type, own_address_type);
+  uint16_t handle = connections_.CreateLeConnection(address, own_address);
   if (handle == acl::kReservedHandle) {
-    LOG_WARN("%s: No pending connection for connection from %s (type %hhx)", __func__, address.ToString().c_str(),
-             address_type);
+    LOG_WARN("%s: No pending connection for connection from %s", __func__,
+             address.ToString().c_str());
     return;
   }
   auto packet = bluetooth::hci::LeConnectionCompleteBuilder::Create(
       ErrorCode::SUCCESS, handle, static_cast<bluetooth::hci::Role>(role),
-      static_cast<bluetooth::hci::AddressType>(address_type), address,
-      connection_interval, connection_latency, supervision_timeout,
+      address.GetAddressType(), address.GetAddress(), connection_interval,
+      connection_latency, supervision_timeout,
       static_cast<bluetooth::hci::MasterClockAccuracy>(0x00));
   send_event_(std::move(packet));
 }
@@ -782,17 +800,26 @@
     model::packets::LinkLayerPacketView incoming) {
   auto connect = model::packets::LeConnectView::Create(incoming);
   ASSERT(connect.IsValid());
-  uint16_t connection_interval = (connect.GetLeConnectionIntervalMax() + connect.GetLeConnectionIntervalMin()) / 2;
-  if (!connections_.CreatePendingLeConnection(incoming.GetSourceAddress(),
-                                              static_cast<uint8_t>(connect.GetAddressType()))) {
-    LOG_WARN("%s: CreatePendingLeConnection failed for connection from %s (type %hhx)", __func__,
-             incoming.GetSourceAddress().ToString().c_str(), connect.GetAddressType());
+  uint16_t connection_interval = (connect.GetLeConnectionIntervalMax() +
+                                  connect.GetLeConnectionIntervalMin()) /
+                                 2;
+  if (!connections_.CreatePendingLeConnection(AddressWithType(
+          incoming.GetSourceAddress(), static_cast<bluetooth::hci::AddressType>(
+                                           connect.GetAddressType())))) {
+    LOG_WARN(
+        "%s: CreatePendingLeConnection failed for connection from %s (type "
+        "%hhx)",
+        __func__, incoming.GetSourceAddress().ToString().c_str(),
+        connect.GetAddressType());
     return;
   }
   HandleLeConnection(
-      incoming.GetSourceAddress(),
-      static_cast<uint8_t>(connect.GetAddressType()),
-      static_cast<uint8_t>(properties_.GetLeAdvertisingOwnAddressType()),
+      AddressWithType(
+          incoming.GetSourceAddress(),
+          static_cast<bluetooth::hci::AddressType>(connect.GetAddressType())),
+      AddressWithType(incoming.GetDestinationAddress(),
+                      static_cast<bluetooth::hci::AddressType>(
+                          properties_.GetLeAdvertisingOwnAddressType())),
       static_cast<uint8_t>(bluetooth::hci::Role::SLAVE), connection_interval,
       connect.GetLeConnectionLatency(),
       connect.GetLeConnectionSupervisionTimeout());
@@ -809,13 +836,16 @@
     model::packets::LinkLayerPacketView incoming) {
   auto complete = model::packets::LeConnectCompleteView::Create(incoming);
   ASSERT(complete.IsValid());
-  HandleLeConnection(incoming.GetSourceAddress(),
-                     static_cast<uint8_t>(complete.GetAddressType()),
-                     static_cast<uint8_t>(le_address_type_),
-                     static_cast<uint8_t>(bluetooth::hci::Role::MASTER),
-                     complete.GetLeConnectionInterval(),
-                     complete.GetLeConnectionLatency(),
-                     complete.GetLeConnectionSupervisionTimeout());
+  HandleLeConnection(
+      AddressWithType(
+          incoming.GetSourceAddress(),
+          static_cast<bluetooth::hci::AddressType>(complete.GetAddressType())),
+      AddressWithType(
+          incoming.GetDestinationAddress(),
+          static_cast<bluetooth::hci::AddressType>(le_address_type_)),
+      static_cast<uint8_t>(bluetooth::hci::Role::MASTER),
+      complete.GetLeConnectionInterval(), complete.GetLeConnectionLatency(),
+      complete.GetLeConnectionSupervisionTimeout());
 }
 
 void LinkLayerController::IncomingLeScanPacket(
@@ -900,7 +930,8 @@
   Address peer = incoming.GetSourceAddress();
   LOG_INFO("%s: %s", __func__, peer.ToString().c_str());
   bool awaiting_authentication = connections_.AuthenticatePendingConnection();
-  uint16_t handle = connections_.CreateConnection(peer);
+  uint16_t handle =
+      connections_.CreateConnection(peer, incoming.GetDestinationAddress());
   if (handle == acl::kReservedHandle) {
     LOG_WARN("%s: No free handles", __func__);
     return;
@@ -1084,7 +1115,7 @@
     const Address& address) {
   security_manager_.DeleteKey(address);
   // Simple pairing to get a key
-  uint16_t handle = connections_.GetHandle(address);
+  uint16_t handle = connections_.GetHandleOnlyAddress(address);
   if (handle == acl::kReservedHandle) {
     LOG_INFO("%s: Device not connected %s", __func__, address.ToString().c_str());
     return ErrorCode::UNKNOWN_CONNECTION;
@@ -1220,9 +1251,11 @@
     return ErrorCode::UNKNOWN_CONNECTION;
   }
 
-  Address remote = connections_.GetAddress(handle);
+  AddressWithType remote = connections_.GetAddress(handle);
 
-  ScheduleTask(milliseconds(5), [this, remote, handle]() { HandleAuthenticationRequest(remote, handle); });
+  ScheduleTask(milliseconds(5), [this, remote, handle]() {
+    HandleAuthenticationRequest(remote.GetAddress(), handle);
+  });
 
   return ErrorCode::SUCCESS;
 }
@@ -1261,14 +1294,15 @@
   if (connections_.IsEncrypted(handle) && !encryption_enable) {
     return ErrorCode::ENCRYPTION_MODE_NOT_ACCEPTABLE;
   }
-  Address remote = connections_.GetAddress(handle);
+  AddressWithType remote = connections_.GetAddress(handle);
 
-  if (security_manager_.ReadKey(remote) == 0) {
+  if (security_manager_.ReadKey(remote.GetAddress()) == 0) {
     return ErrorCode::PIN_OR_KEY_MISSING;
   }
 
   ScheduleTask(milliseconds(5), [this, remote, handle, encryption_enable]() {
-    HandleSetConnectionEncryption(remote, handle, encryption_enable);
+    HandleSetConnectionEncryption(remote.GetAddress(), handle,
+                                  encryption_enable);
   });
   return ErrorCode::SUCCESS;
 }
@@ -1295,7 +1329,8 @@
       properties_.GetAddress(), addr, try_role_switch);
   SendLinkLayerPacket(std::move(to_send));
 
-  uint16_t handle = connections_.CreateConnection(addr);
+  uint16_t handle =
+      connections_.CreateConnection(addr, properties_.GetAddress());
   if (handle == acl::kReservedHandle) {
     LOG_INFO("%s CreateConnection failed", __func__);
     return;
@@ -1356,14 +1391,13 @@
 }
 
 ErrorCode LinkLayerController::Disconnect(uint16_t handle, uint8_t reason) {
-  // TODO: Handle LE
   if (!connections_.HasHandle(handle)) {
     return ErrorCode::UNKNOWN_CONNECTION;
   }
 
-  const Address& remote = connections_.GetAddress(handle);
+  const AddressWithType remote = connections_.GetAddress(handle);
   auto packet = model::packets::DisconnectBuilder::Create(
-      properties_.GetAddress(), remote, reason);
+      properties_.GetAddress(), remote.GetAddress(), reason);
   SendLinkLayerPacket(std::move(packet));
   ASSERT_LOG(connections_.Disconnect(handle), "Disconnecting %hx", handle);
 
diff --git a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
index b287123..79027ec 100644
--- a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
+++ b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
@@ -131,8 +131,10 @@
 
   void LeAdvertising();
 
-  void HandleLeConnection(Address addr, uint8_t addr_type, uint8_t own_addr_type, uint8_t role,
-                          uint16_t connection_interval, uint16_t connection_latency, uint16_t supervision_timeout);
+  void HandleLeConnection(AddressWithType addr, AddressWithType own_addr,
+                          uint8_t role, uint16_t connection_interval,
+                          uint16_t connection_latency,
+                          uint16_t supervision_timeout);
 
   void LeWhiteListClear();
   void LeWhiteListAddDevice(Address addr, uint8_t addr_type);