Merge "SecurityManager: Classic Pairing Handler"
am: 1b410fbbec

Change-Id: I0fb84de7f858e29c60844b0b717ecb5bb28b61bc
diff --git a/gd/l2cap/classic/fixed_channel_manager.h b/gd/l2cap/classic/fixed_channel_manager.h
index 5e8f6ab..65c0b73 100644
--- a/gd/l2cap/classic/fixed_channel_manager.h
+++ b/gd/l2cap/classic/fixed_channel_manager.h
@@ -142,6 +142,7 @@
   FixedChannelManager(internal::FixedChannelServiceManagerImpl* service_manager, internal::LinkManager* link_manager,
                       os::Handler* l2cap_layer_handler)
       : service_manager_(service_manager), link_manager_(link_manager), l2cap_layer_handler_(l2cap_layer_handler) {}
+
   internal::FixedChannelServiceManagerImpl* service_manager_ = nullptr;
   internal::LinkManager* link_manager_ = nullptr;
   os::Handler* l2cap_layer_handler_ = nullptr;
diff --git a/gd/security/Android.bp b/gd/security/Android.bp
index 7762461..7407f6d 100644
--- a/gd/security/Android.bp
+++ b/gd/security/Android.bp
@@ -11,6 +11,7 @@
         "internal/security_manager_impl.cc",
         "security_module.cc",
         ":BluetoothSecurityChannelSources",
+        ":BluetoothSecurityPairingSources",
     ],
 }
 
@@ -22,5 +23,6 @@
         "test/fake_l2cap_test.cc",
         "test/pairing_handler_le_pair_test.cc",
         ":BluetoothSecurityChannelTestSources",
+        ":BluetoothSecurityPairingTestSources",
     ],
 }
diff --git a/gd/security/channel/security_manager_channel.cc b/gd/security/channel/security_manager_channel.cc
index 331bbec..fd6e9df 100644
--- a/gd/security/channel/security_manager_channel.cc
+++ b/gd/security/channel/security_manager_channel.cc
@@ -1,4 +1,4 @@
-/******************************************************************************
+/*
  *
  *  Copyright 2019 The Android Open Source Project
  *
@@ -14,80 +14,32 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- ******************************************************************************/
-#include "security_manager_channel.h"
+ */
+#include "security/channel/security_manager_channel.h"
 
 #include "security/smp_packets.h"
 
-using namespace bluetooth::hci;
-using namespace bluetooth::packet;
-using namespace bluetooth::security::channel;
+namespace bluetooth {
+namespace security {
+namespace channel {
 
-void SecurityManagerChannel::SendCommand(std::shared_ptr<hci::Device> device,
-                                         std::unique_ptr<SecurityCommandBuilder> command) {
+void SecurityManagerChannel::OnCommandComplete(hci::CommandCompleteView packet) {
+  ASSERT(packet.IsValid());
+  // TODO(optedoblivion): Verify HCI commands
+}
+
+void SecurityManagerChannel::SendCommand(std::unique_ptr<hci::SecurityCommandBuilder> command) {
   hci_security_interface_->EnqueueCommand(
       std::move(command), common::BindOnce(&SecurityManagerChannel::OnCommandComplete, common::Unretained(this)),
       handler_);
 }
 
-void SecurityManagerChannel::OnCommandComplete(CommandCompleteView packet) {
-  ASSERT_LOG(packet.IsValid(), "Received invalid packet: %hx", packet.GetCommandOpCode());
-  // TODO(optedoblivion): Verify HCI commands
+void SecurityManagerChannel::OnHciEventReceived(hci::EventPacketView packet) {
+  ASSERT_LOG(listener_ != nullptr, "No listener set!");
+  ASSERT(packet.IsValid());
+  listener_->OnHciEventReceived(packet);
 }
 
-void SecurityManagerChannel::OnHciEventReceived(EventPacketView packet) {
-  ASSERT_LOG(listener_ != nullptr, "No listener set!");
-  std::shared_ptr<Device> device = nullptr;
-  auto event = EventPacketView::Create(std::move(packet));
-  ASSERT_LOG(event.IsValid(), "Received invalid packet");
-  const hci::EventCode code = event.GetEventCode();
-  switch (code) {
-    case hci::EventCode::CHANGE_CONNECTION_LINK_KEY_COMPLETE:
-      listener_->OnChangeConnectionLinkKeyComplete(device,
-                                                   hci::ChangeConnectionLinkKeyCompleteView::Create(std::move(event)));
-      break;
-    case hci::EventCode::MASTER_LINK_KEY_COMPLETE:
-      listener_->OnMasterLinkKeyComplete(device, hci::MasterLinkKeyCompleteView::Create(std::move(event)));
-      break;
-    case hci::EventCode::PIN_CODE_REQUEST:
-      listener_->OnPinCodeRequest(device, hci::PinCodeRequestView::Create(std::move(event)));
-      break;
-    case hci::EventCode::LINK_KEY_REQUEST:
-      listener_->OnLinkKeyRequest(device, hci::LinkKeyRequestView::Create(std::move(event)));
-      break;
-    case hci::EventCode::LINK_KEY_NOTIFICATION:
-      listener_->OnLinkKeyNotification(device, hci::LinkKeyNotificationView::Create(std::move(event)));
-      break;
-    case hci::EventCode::IO_CAPABILITY_REQUEST:
-      listener_->OnIoCapabilityRequest(device, hci::IoCapabilityRequestView::Create(std::move(event)));
-      break;
-    case hci::EventCode::IO_CAPABILITY_RESPONSE:
-      listener_->OnIoCapabilityResponse(device, IoCapabilityResponseView::Create(std::move(event)));
-      break;
-    case hci::EventCode::SIMPLE_PAIRING_COMPLETE:
-      listener_->OnSimplePairingComplete(device, SimplePairingCompleteView::Create(std::move(event)));
-      break;
-    case hci::EventCode::RETURN_LINK_KEYS:
-      listener_->OnReturnLinkKeys(device, hci::ReturnLinkKeysView::Create(std::move(event)));
-      break;
-    case hci::EventCode::ENCRYPTION_CHANGE:
-      listener_->OnEncryptionChange(device, hci::EncryptionChangeView::Create(std::move(event)));
-      break;
-    case hci::EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE:
-      listener_->OnEncryptionKeyRefreshComplete(device,
-                                                hci::EncryptionKeyRefreshCompleteView::Create(std::move(event)));
-      break;
-    case hci::EventCode::REMOTE_OOB_DATA_REQUEST:
-      listener_->OnRemoteOobDataRequest(device, hci::RemoteOobDataRequestView::Create(std::move(event)));
-      break;
-    case hci::EventCode::USER_PASSKEY_NOTIFICATION:
-      listener_->OnUserPasskeyNotification(device, hci::UserPasskeyNotificationView::Create(std::move(event)));
-      break;
-    case hci::EventCode::KEYPRESS_NOTIFICATION:
-      listener_->OnKeypressNotification(device, hci::KeypressNotificationView::Create(std::move(event)));
-      break;
-    default:
-      ASSERT_LOG(false, "Invalid packet received: %hhx", code);
-      break;
-  }
-}
+}  // namespace channel
+}  // namespace security
+}  // namespace bluetooth
diff --git a/gd/security/channel/security_manager_channel.h b/gd/security/channel/security_manager_channel.h
index 02d0357..e844a4c 100644
--- a/gd/security/channel/security_manager_channel.h
+++ b/gd/security/channel/security_manager_channel.h
@@ -1,4 +1,4 @@
-/******************************************************************************
+/*
  *
  *  Copyright 2019 The Android Open Source Project
  *
@@ -14,50 +14,28 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- ******************************************************************************/
+ */
 #pragma once
 
 #include <memory>
 #include <vector>
 
-#include "hci/classic_device.h"
+#include "hci/address_with_type.h"
 #include "hci/hci_layer.h"
+#include "hci/hci_packets.h"
 #include "hci/security_interface.h"
-#include "security/smp_packets.h"
 
 namespace bluetooth {
 namespace security {
 namespace channel {
 
-using hci::CommandCompleteView;
-using hci::EventPacketView;
-using hci::SecurityCommandBuilder;
-using hci::SecurityCommandView;
-
 /**
  * Interface for listening to the channel for SMP commands.
  */
 class ISecurityManagerChannelListener {
  public:
   virtual ~ISecurityManagerChannelListener() = default;
-
-  virtual void OnChangeConnectionLinkKeyComplete(std::shared_ptr<hci::Device> device,
-                                                 hci::ChangeConnectionLinkKeyCompleteView packet) = 0;
-  virtual void OnMasterLinkKeyComplete(std::shared_ptr<hci::Device> device, hci::MasterLinkKeyCompleteView packet) = 0;
-  virtual void OnPinCodeRequest(std::shared_ptr<hci::Device> device, hci::PinCodeRequestView packet) = 0;
-  virtual void OnLinkKeyRequest(std::shared_ptr<hci::Device> device, hci::LinkKeyRequestView packet) = 0;
-  virtual void OnLinkKeyNotification(std::shared_ptr<hci::Device> device, hci::LinkKeyNotificationView packet) = 0;
-  virtual void OnIoCapabilityRequest(std::shared_ptr<hci::Device> device, hci::IoCapabilityRequestView packet) = 0;
-  virtual void OnIoCapabilityResponse(std::shared_ptr<hci::Device> device, hci::IoCapabilityResponseView packet) = 0;
-  virtual void OnSimplePairingComplete(std::shared_ptr<hci::Device> device, hci::SimplePairingCompleteView packet) = 0;
-  virtual void OnReturnLinkKeys(std::shared_ptr<hci::Device> device, hci::ReturnLinkKeysView packet) = 0;
-  virtual void OnEncryptionChange(std::shared_ptr<hci::Device> device, hci::EncryptionChangeView packet) = 0;
-  virtual void OnEncryptionKeyRefreshComplete(std::shared_ptr<hci::Device> device,
-                                              hci::EncryptionKeyRefreshCompleteView packet) = 0;
-  virtual void OnRemoteOobDataRequest(std::shared_ptr<hci::Device> device, hci::RemoteOobDataRequestView packet) = 0;
-  virtual void OnUserPasskeyNotification(std::shared_ptr<hci::Device> device,
-                                         hci::UserPasskeyNotificationView packet) = 0;
-  virtual void OnKeypressNotification(std::shared_ptr<hci::Device> device, hci::KeypressNotificationView packet) = 0;
+  virtual void OnHciEventReceived(hci::EventPacketView packet) = 0;
 };
 
 /**
@@ -77,10 +55,9 @@
   /**
    * Send a given SMP command over the SecurityManagerChannel
    *
-   * @param device target where command will be sent
    * @param command smp command to send
    */
-  void SendCommand(std::shared_ptr<hci::Device> device, std::unique_ptr<SecurityCommandBuilder> command);
+  void SendCommand(std::unique_ptr<hci::SecurityCommandBuilder> command);
 
   /**
    * Sets the listener to listen for channel events
@@ -96,14 +73,14 @@
    *
    * @param event_packet
    */
-  void OnHciEventReceived(EventPacketView packet);
+  void OnHciEventReceived(hci::EventPacketView packet);
 
   /**
    * Called when an HCI command is completed
    *
    * @param on_complete
    */
-  void OnCommandComplete(CommandCompleteView packet);
+  void OnCommandComplete(hci::CommandCompleteView packet);
 
  private:
   ISecurityManagerChannelListener* listener_;
diff --git a/gd/security/channel/security_manager_channel_unittest.cc b/gd/security/channel/security_manager_channel_unittest.cc
index b111e7f..ee12b92 100644
--- a/gd/security/channel/security_manager_channel_unittest.cc
+++ b/gd/security/channel/security_manager_channel_unittest.cc
@@ -1,4 +1,4 @@
-/******************************************************************************
+/*
  *
  *  Copyright 2019 The Android Open Source Project
  *
@@ -14,13 +14,11 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- ******************************************************************************/
+ */
 #include "security_manager_channel.h"
 
 #include <gtest/gtest.h>
 
-#include "hci/device.h"
-#include "hci/device_database.h"
 #include "hci/hci_packets.h"
 #include "packet/raw_builder.h"
 #include "security/smp_packets.h"
@@ -32,10 +30,9 @@
 namespace {
 
 using bluetooth::security::channel::SecurityManagerChannel;
+using hci::Address;
 using hci::AuthenticationRequirements;
 using hci::CommandCompleteBuilder;
-using hci::Device;
-using hci::DeviceDatabase;
 using hci::IoCapabilityRequestReplyBuilder;
 using hci::IoCapabilityRequestView;
 using hci::OobDataPresent;
@@ -44,8 +41,6 @@
 using os::Thread;
 using packet::RawBuilder;
 
-static DeviceDatabase kDeviceDatabase;
-
 class SecurityManagerChannelCallback : public ISecurityManagerChannelListener {
  public:
   // HCI
@@ -62,71 +57,138 @@
   bool receivedEncryptionKeyRefreshComplete = false;
   bool receivedRemoteOobDataRequest = false;
   bool receivedUserPasskeyNotification = false;
+  bool receivedUserPasskeyRequest = false;
   bool receivedKeypressNotification = false;
+  bool receivedUserConfirmationRequest = false;
 
-  void OnChangeConnectionLinkKeyComplete(std::shared_ptr<hci::Device> device,
-                                         hci::ChangeConnectionLinkKeyCompleteView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::ChangeConnectionLinkKeyCompleteView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedChangeConnectionLinkKeyComplete = true;
   }
-  void OnMasterLinkKeyComplete(std::shared_ptr<hci::Device> device, hci::MasterLinkKeyCompleteView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::MasterLinkKeyCompleteView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedMasterLinkKeyComplete = true;
   }
-  void OnPinCodeRequest(std::shared_ptr<hci::Device> device, hci::PinCodeRequestView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::PinCodeRequestView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedPinCodeRequest = true;
   }
-  void OnLinkKeyRequest(std::shared_ptr<hci::Device> device, hci::LinkKeyRequestView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::LinkKeyRequestView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedLinkKeyRequest = true;
   }
-  void OnLinkKeyNotification(std::shared_ptr<hci::Device> device, hci::LinkKeyNotificationView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::LinkKeyNotificationView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedLinkKeyNotification = true;
   }
-  void OnIoCapabilityRequest(std::shared_ptr<Device> device, hci::IoCapabilityRequestView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::IoCapabilityRequestView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedIoCapabilityRequest = true;
   }
-  void OnIoCapabilityResponse(std::shared_ptr<Device> device, hci::IoCapabilityResponseView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::IoCapabilityResponseView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedIoCapabilityResponse = true;
   }
-  void OnSimplePairingComplete(std::shared_ptr<Device> device, hci::SimplePairingCompleteView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::SimplePairingCompleteView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedSimplePairingComplete = true;
   }
-  void OnReturnLinkKeys(std::shared_ptr<Device> device, hci::ReturnLinkKeysView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::ReturnLinkKeysView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedReturnLinkKeys = true;
   }
-  void OnEncryptionChange(std::shared_ptr<Device> device, hci::EncryptionChangeView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::EncryptionChangeView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedEncryptionChange = true;
   }
-  void OnEncryptionKeyRefreshComplete(std::shared_ptr<Device> device, hci::EncryptionKeyRefreshCompleteView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::EncryptionKeyRefreshCompleteView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedEncryptionKeyRefreshComplete = true;
   }
-  void OnRemoteOobDataRequest(std::shared_ptr<Device> device, hci::RemoteOobDataRequestView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::RemoteOobDataRequestView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedRemoteOobDataRequest = true;
   }
-  void OnUserPasskeyNotification(std::shared_ptr<hci::Device> device, hci::UserPasskeyNotificationView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::UserPasskeyNotificationView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedUserPasskeyNotification = true;
   }
-  void OnKeypressNotification(std::shared_ptr<hci::Device> device, hci::KeypressNotificationView packet) {
-    EXPECT_TRUE(packet.IsValid());
+  void OnReceive(hci::AddressWithType device, hci::KeypressNotificationView packet) {
+    ASSERT_TRUE(packet.IsValid());
     receivedKeypressNotification = true;
   }
+  void OnReceive(hci::AddressWithType device, hci::UserConfirmationRequestView packet) {
+    ASSERT_TRUE(packet.IsValid());
+    receivedUserConfirmationRequest = true;
+  }
+  void OnReceive(hci::AddressWithType device, hci::UserPasskeyRequestView packet) {
+    ASSERT_TRUE(packet.IsValid());
+    receivedUserPasskeyRequest = true;
+  }
+
+  void OnHciEventReceived(EventPacketView packet) override {
+    auto event = EventPacketView::Create(packet);
+    ASSERT_LOG(event.IsValid(), "Received invalid packet");
+    const hci::EventCode code = event.GetEventCode();
+    switch (code) {
+      case hci::EventCode::CHANGE_CONNECTION_LINK_KEY_COMPLETE:
+        OnReceive(hci::AddressWithType(), hci::ChangeConnectionLinkKeyCompleteView::Create(event));
+        break;
+      case hci::EventCode::MASTER_LINK_KEY_COMPLETE:
+        OnReceive(hci::AddressWithType(), hci::MasterLinkKeyCompleteView::Create(event));
+        break;
+      case hci::EventCode::PIN_CODE_REQUEST:
+        OnReceive(hci::AddressWithType(), hci::PinCodeRequestView::Create(event));
+        break;
+      case hci::EventCode::LINK_KEY_REQUEST:
+        OnReceive(hci::AddressWithType(), hci::LinkKeyRequestView::Create(event));
+        break;
+      case hci::EventCode::LINK_KEY_NOTIFICATION:
+        OnReceive(hci::AddressWithType(), hci::LinkKeyNotificationView::Create(event));
+        break;
+      case hci::EventCode::IO_CAPABILITY_REQUEST:
+        OnReceive(hci::AddressWithType(), hci::IoCapabilityRequestView::Create(event));
+        break;
+      case hci::EventCode::IO_CAPABILITY_RESPONSE:
+        OnReceive(hci::AddressWithType(), hci::IoCapabilityResponseView::Create(event));
+        break;
+      case hci::EventCode::SIMPLE_PAIRING_COMPLETE:
+        OnReceive(hci::AddressWithType(), hci::SimplePairingCompleteView::Create(event));
+        break;
+      case hci::EventCode::RETURN_LINK_KEYS:
+        OnReceive(hci::AddressWithType(), hci::ReturnLinkKeysView::Create(event));
+        break;
+      case hci::EventCode::ENCRYPTION_CHANGE:
+        OnReceive(hci::AddressWithType(), hci::EncryptionChangeView::Create(event));
+        break;
+      case hci::EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE:
+        OnReceive(hci::AddressWithType(), hci::EncryptionKeyRefreshCompleteView::Create(event));
+        break;
+      case hci::EventCode::REMOTE_OOB_DATA_REQUEST:
+        OnReceive(hci::AddressWithType(), hci::RemoteOobDataRequestView::Create(event));
+        break;
+      case hci::EventCode::USER_PASSKEY_NOTIFICATION:
+        OnReceive(hci::AddressWithType(), hci::UserPasskeyNotificationView::Create(event));
+        break;
+      case hci::EventCode::KEYPRESS_NOTIFICATION:
+        OnReceive(hci::AddressWithType(), hci::KeypressNotificationView::Create(event));
+        break;
+      case hci::EventCode::USER_CONFIRMATION_REQUEST:
+        OnReceive(hci::AddressWithType(), hci::UserConfirmationRequestView::Create(event));
+        break;
+      case hci::EventCode::USER_PASSKEY_REQUEST:
+        OnReceive(hci::AddressWithType(), hci::UserPasskeyRequestView::Create(event));
+        break;
+      default:
+        ASSERT_LOG(false, "Cannot handle received packet: %s", hci::EventCodeText(code).c_str());
+        break;
+    }
+  }
 };
 
 class SecurityManagerChannelTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    device_ = kDeviceDatabase.CreateClassicDevice(hci::Address({0x01, 0x02, 0x03, 0x04, 0x05, 0x06}));
     handler_ = new Handler(&thread_);
     callback_ = new SecurityManagerChannelCallback();
     hci_layer_ = new FakeHciLayer();
@@ -152,14 +214,14 @@
   FakeHciLayer* hci_layer_ = nullptr;
   SecurityManagerChannel* channel_ = nullptr;
   SecurityManagerChannelCallback* callback_ = nullptr;
-  std::shared_ptr<Device> device_ = nullptr;
+  hci::AddressWithType device_;
 };
 
 TEST_F(SecurityManagerChannelTest, setup_teardown) {}
 
 TEST_F(SecurityManagerChannelTest, recv_io_cap_request) {
-  hci_layer_->IncomingEvent(hci::IoCapabilityRequestBuilder::Create(device_->GetAddress()));
-  EXPECT_TRUE(callback_->receivedIoCapabilityRequest);
+  hci_layer_->IncomingEvent(hci::IoCapabilityRequestBuilder::Create(device_.GetAddress()));
+  ASSERT_TRUE(callback_->receivedIoCapabilityRequest);
 }
 
 TEST_F(SecurityManagerChannelTest, send_io_cap_request_reply) {
@@ -167,153 +229,159 @@
   hci::IoCapability io_capability = (hci::IoCapability)0x00;
   OobDataPresent oob_present = (OobDataPresent)0x00;
   AuthenticationRequirements authentication_requirements = (AuthenticationRequirements)0x00;
-  auto packet = hci::IoCapabilityRequestReplyBuilder::Create(device_->GetAddress(), io_capability, oob_present,
+  auto packet = hci::IoCapabilityRequestReplyBuilder::Create(device_.GetAddress(), io_capability, oob_present,
                                                              authentication_requirements);
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, send_io_cap_request_neg_reply) {
   // Arrange
   auto packet =
-      hci::IoCapabilityRequestNegativeReplyBuilder::Create(device_->GetAddress(), hci::ErrorCode::COMMAND_DISALLOWED);
+      hci::IoCapabilityRequestNegativeReplyBuilder::Create(device_.GetAddress(), hci::ErrorCode::COMMAND_DISALLOWED);
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, recv_io_cap_response) {
   hci::IoCapability io_capability = (hci::IoCapability)0x00;
   OobDataPresent oob_present = (OobDataPresent)0x00;
   AuthenticationRequirements authentication_requirements = (AuthenticationRequirements)0x00;
-  hci_layer_->IncomingEvent(hci::IoCapabilityResponseBuilder::Create(device_->GetAddress(), io_capability, oob_present,
+  hci_layer_->IncomingEvent(hci::IoCapabilityResponseBuilder::Create(device_.GetAddress(), io_capability, oob_present,
                                                                      authentication_requirements));
-  EXPECT_TRUE(callback_->receivedIoCapabilityResponse);
+  ASSERT_TRUE(callback_->receivedIoCapabilityResponse);
 }
 
 TEST_F(SecurityManagerChannelTest, recv_pin_code_request) {
-  hci_layer_->IncomingEvent(hci::PinCodeRequestBuilder::Create(device_->GetAddress()));
-  EXPECT_TRUE(callback_->receivedPinCodeRequest);
+  hci_layer_->IncomingEvent(hci::PinCodeRequestBuilder::Create(device_.GetAddress()));
+  ASSERT_TRUE(callback_->receivedPinCodeRequest);
 }
 
 TEST_F(SecurityManagerChannelTest, send_pin_code_request_reply) {
   // Arrange
   uint8_t pin_code_length = 6;
   std::array<uint8_t, 16> pin_code = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
-  auto packet = hci::PinCodeRequestReplyBuilder::Create(device_->GetAddress(), pin_code_length, pin_code);
+  auto packet = hci::PinCodeRequestReplyBuilder::Create(device_.GetAddress(), pin_code_length, pin_code);
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::PIN_CODE_REQUEST_REPLY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::PIN_CODE_REQUEST_REPLY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, send_pin_code_request_neg_reply) {
   // Arrange
-  auto packet = hci::PinCodeRequestNegativeReplyBuilder::Create(device_->GetAddress());
+  auto packet = hci::PinCodeRequestNegativeReplyBuilder::Create(device_.GetAddress());
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::PIN_CODE_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::PIN_CODE_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, recv_user_passkey_notification) {
   uint32_t passkey = 0x00;
-  hci_layer_->IncomingEvent(hci::UserPasskeyNotificationBuilder::Create(device_->GetAddress(), passkey));
-  EXPECT_TRUE(callback_->receivedUserPasskeyNotification);
+  hci_layer_->IncomingEvent(hci::UserPasskeyNotificationBuilder::Create(device_.GetAddress(), passkey));
+  ASSERT_TRUE(callback_->receivedUserPasskeyNotification);
+}
+
+TEST_F(SecurityManagerChannelTest, recv_user_confirmation_request) {
+  uint32_t numeric_value = 0x0;
+  hci_layer_->IncomingEvent(hci::UserConfirmationRequestBuilder::Create(device_.GetAddress(), numeric_value));
+  ASSERT_TRUE(callback_->receivedUserConfirmationRequest);
 }
 
 TEST_F(SecurityManagerChannelTest, send_user_confirmation_request_reply) {
   // Arrange
-  auto packet = hci::UserConfirmationRequestReplyBuilder::Create(device_->GetAddress());
+  auto packet = hci::UserConfirmationRequestReplyBuilder::Create(device_.GetAddress());
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, packet_view.GetOpCode());
 }
 
-TEST_F(SecurityManagerChannelTest, send_user_confirmation_request_neg_reply) {
+TEST_F(SecurityManagerChannelTest, send_user_confirmation_request_negative_reply) {
   // Arrange
-  auto packet = hci::UserConfirmationRequestNegativeReplyBuilder::Create(device_->GetAddress());
+  auto packet = hci::UserConfirmationRequestNegativeReplyBuilder::Create(device_.GetAddress());
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, recv_remote_oob_data_request) {
-  hci_layer_->IncomingEvent(hci::RemoteOobDataRequestBuilder::Create(device_->GetAddress()));
-  EXPECT_TRUE(callback_->receivedRemoteOobDataRequest);
+  hci_layer_->IncomingEvent(hci::RemoteOobDataRequestBuilder::Create(device_.GetAddress()));
+  ASSERT_TRUE(callback_->receivedRemoteOobDataRequest);
 }
 
 TEST_F(SecurityManagerChannelTest, send_remote_oob_data_request_reply) {
   // Arrange
   std::array<uint8_t, 16> c = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
   std::array<uint8_t, 16> r = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
-  auto packet = hci::RemoteOobDataRequestReplyBuilder::Create(device_->GetAddress(), c, r);
+  auto packet = hci::RemoteOobDataRequestReplyBuilder::Create(device_.GetAddress(), c, r);
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::REMOTE_OOB_DATA_REQUEST_REPLY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::REMOTE_OOB_DATA_REQUEST_REPLY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, send_remote_oob_data_request_neg_reply) {
   // Arrange
-  auto packet = hci::RemoteOobDataRequestNegativeReplyBuilder::Create(device_->GetAddress());
+  auto packet = hci::RemoteOobDataRequestNegativeReplyBuilder::Create(device_.GetAddress());
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, send_read_local_oob_data) {
@@ -321,14 +389,14 @@
   auto packet = hci::ReadLocalOobDataBuilder::Create();
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::READ_LOCAL_OOB_DATA, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::READ_LOCAL_OOB_DATA, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, send_read_local_oob_extended_data) {
@@ -336,92 +404,92 @@
   auto packet = hci::ReadLocalOobExtendedDataBuilder::Create();
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::READ_LOCAL_OOB_EXTENDED_DATA, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::READ_LOCAL_OOB_EXTENDED_DATA, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, recv_link_key_request) {
-  hci_layer_->IncomingEvent(hci::LinkKeyRequestBuilder::Create(device_->GetAddress()));
-  EXPECT_TRUE(callback_->receivedLinkKeyRequest);
+  hci_layer_->IncomingEvent(hci::LinkKeyRequestBuilder::Create(device_.GetAddress()));
+  ASSERT_TRUE(callback_->receivedLinkKeyRequest);
 }
 
 TEST_F(SecurityManagerChannelTest, recv_link_key_notification) {
   std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
   hci_layer_->IncomingEvent(
-      hci::LinkKeyNotificationBuilder::Create(device_->GetAddress(), link_key, hci::KeyType::DEBUG_COMBINATION));
-  EXPECT_TRUE(callback_->receivedLinkKeyNotification);
+      hci::LinkKeyNotificationBuilder::Create(device_.GetAddress(), link_key, hci::KeyType::DEBUG_COMBINATION));
+  ASSERT_TRUE(callback_->receivedLinkKeyNotification);
 }
 
 TEST_F(SecurityManagerChannelTest, recv_master_link_key_complete) {
   uint16_t connection_handle = 0x0;
   hci_layer_->IncomingEvent(
       hci::MasterLinkKeyCompleteBuilder::Create(hci::ErrorCode::SUCCESS, connection_handle, hci::KeyFlag::TEMPORARY));
-  EXPECT_TRUE(callback_->receivedMasterLinkKeyComplete);
+  ASSERT_TRUE(callback_->receivedMasterLinkKeyComplete);
 }
 
 TEST_F(SecurityManagerChannelTest, recv_change_connection_link_key_complete) {
   uint16_t connection_handle = 0x0;
   hci_layer_->IncomingEvent(
       hci::ChangeConnectionLinkKeyCompleteBuilder::Create(hci::ErrorCode::SUCCESS, connection_handle));
-  EXPECT_TRUE(callback_->receivedChangeConnectionLinkKeyComplete);
+  ASSERT_TRUE(callback_->receivedChangeConnectionLinkKeyComplete);
 }
 
 TEST_F(SecurityManagerChannelTest, recv_return_link_keys) {
   std::vector<hci::ZeroKeyAndAddress> keys;
   hci_layer_->IncomingEvent(hci::ReturnLinkKeysBuilder::Create(keys));
-  EXPECT_TRUE(callback_->receivedReturnLinkKeys);
+  ASSERT_TRUE(callback_->receivedReturnLinkKeys);
 }
 
 TEST_F(SecurityManagerChannelTest, send_link_key_request_reply) {
   // Arrange
   std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
-  auto packet = hci::LinkKeyRequestReplyBuilder::Create(device_->GetAddress(), link_key);
+  auto packet = hci::LinkKeyRequestReplyBuilder::Create(device_.GetAddress(), link_key);
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::LINK_KEY_REQUEST_REPLY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::LINK_KEY_REQUEST_REPLY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, send_link_key_request_neg_reply) {
   // Arrange
-  auto packet = hci::LinkKeyRequestNegativeReplyBuilder::Create(device_->GetAddress());
+  auto packet = hci::LinkKeyRequestNegativeReplyBuilder::Create(device_.GetAddress());
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, send_read_stored_link_key) {
   // Arrange
-  auto packet = hci::ReadStoredLinkKeyBuilder::Create(device_->GetAddress(), hci::ReadStoredLinkKeyReadAllFlag::ALL);
+  auto packet = hci::ReadStoredLinkKeyBuilder::Create(device_.GetAddress(), hci::ReadStoredLinkKeyReadAllFlag::ALL);
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::READ_STORED_LINK_KEY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::READ_STORED_LINK_KEY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, send_write_stored_link_key) {
@@ -430,37 +498,44 @@
   auto packet = hci::WriteStoredLinkKeyBuilder::Create(keys_to_write);
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::WRITE_STORED_LINK_KEY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::WRITE_STORED_LINK_KEY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, send_delete_stored_link_key) {
   // Arrange
   auto packet =
-      hci::DeleteStoredLinkKeyBuilder::Create(device_->GetAddress(), hci::DeleteStoredLinkKeyDeleteAllFlag::ALL);
+      hci::DeleteStoredLinkKeyBuilder::Create(device_.GetAddress(), hci::DeleteStoredLinkKeyDeleteAllFlag::ALL);
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::DELETE_STORED_LINK_KEY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::DELETE_STORED_LINK_KEY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, recv_encryption_change) {
   uint16_t connection_handle = 0x0;
   hci_layer_->IncomingEvent(
       hci::EncryptionChangeBuilder::Create(hci::ErrorCode::SUCCESS, connection_handle, hci::EncryptionEnabled::ON));
-  EXPECT_TRUE(callback_->receivedEncryptionChange);
+  ASSERT_TRUE(callback_->receivedEncryptionChange);
+}
+
+TEST_F(SecurityManagerChannelTest, recv_encryption_key_refresh) {
+  uint16_t connection_handle = 0x0;
+  hci_layer_->IncomingEvent(
+      hci::EncryptionKeyRefreshCompleteBuilder::Create(hci::ErrorCode::SUCCESS, connection_handle));
+  ASSERT_TRUE(callback_->receivedEncryptionKeyRefreshComplete);
 }
 
 TEST_F(SecurityManagerChannelTest, send_refresh_encryption_key) {
@@ -469,14 +544,14 @@
   auto packet = hci::RefreshEncryptionKeyBuilder::Create(connection_handle);
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::REFRESH_ENCRYPTION_KEY, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::REFRESH_ENCRYPTION_KEY, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, send_read_encryption_key_size) {
@@ -485,19 +560,19 @@
   auto packet = hci::ReadEncryptionKeySizeBuilder::Create(connection_handle);
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::READ_ENCRYPTION_KEY_SIZE, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::READ_ENCRYPTION_KEY_SIZE, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, recv_simple_pairing_complete) {
-  hci_layer_->IncomingEvent(hci::SimplePairingCompleteBuilder::Create(hci::ErrorCode::SUCCESS, device_->GetAddress()));
-  EXPECT_TRUE(callback_->receivedSimplePairingComplete);
+  hci_layer_->IncomingEvent(hci::SimplePairingCompleteBuilder::Create(hci::ErrorCode::SUCCESS, device_.GetAddress()));
+  ASSERT_TRUE(callback_->receivedSimplePairingComplete);
 }
 
 TEST_F(SecurityManagerChannelTest, send_read_simple_pairing_mode) {
@@ -505,14 +580,14 @@
   auto packet = hci::ReadSimplePairingModeBuilder::Create();
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::READ_SIMPLE_PAIRING_MODE, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::READ_SIMPLE_PAIRING_MODE, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, send_write_simple_pairing_mode) {
@@ -520,36 +595,41 @@
   auto packet = hci::WriteSimplePairingModeBuilder::Create(hci::Enable::ENABLED);
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::WRITE_SIMPLE_PAIRING_MODE, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::WRITE_SIMPLE_PAIRING_MODE, packet_view.GetOpCode());
 }
 
 TEST_F(SecurityManagerChannelTest, recv_keypress_notification) {
   hci_layer_->IncomingEvent(
-      hci::KeypressNotificationBuilder::Create(device_->GetAddress(), hci::KeypressNotificationType::ENTRY_COMPLETED));
-  EXPECT_TRUE(callback_->receivedKeypressNotification);
+      hci::KeypressNotificationBuilder::Create(device_.GetAddress(), hci::KeypressNotificationType::ENTRY_COMPLETED));
+  ASSERT_TRUE(callback_->receivedKeypressNotification);
 }
 
 TEST_F(SecurityManagerChannelTest, send_keypress_notification) {
   // Arrange
   auto packet =
-      hci::SendKeypressNotificationBuilder::Create(device_->GetAddress(), hci::KeypressNotificationType::ENTRY_STARTED);
+      hci::SendKeypressNotificationBuilder::Create(device_.GetAddress(), hci::KeypressNotificationType::ENTRY_STARTED);
 
   // Act
-  channel_->SendCommand(device_, std::move(packet));
+  channel_->SendCommand(std::move(packet));
   auto last_command = std::move(hci_layer_->GetLastCommand()->command);
   auto command_packet = GetPacketView(std::move(last_command));
   hci::CommandPacketView packet_view = hci::CommandPacketView::Create(command_packet);
 
   // Assert
-  EXPECT_TRUE(packet_view.IsValid());
-  EXPECT_EQ(OpCode::SEND_KEYPRESS_NOTIFICATION, packet_view.GetOpCode());
+  ASSERT_TRUE(packet_view.IsValid());
+  ASSERT_EQ(OpCode::SEND_KEYPRESS_NOTIFICATION, packet_view.GetOpCode());
+}
+
+TEST_F(SecurityManagerChannelTest, recv_user_passkey_request) {
+  hci_layer_->IncomingEvent(hci::UserPasskeyRequestBuilder::Create(device_.GetAddress()));
+  ASSERT_TRUE(callback_->receivedUserPasskeyRequest);
 }
 
 }  // namespace
diff --git a/gd/security/internal/security_manager_impl.cc b/gd/security/internal/security_manager_impl.cc
index b245ff9..92556c3 100644
--- a/gd/security/internal/security_manager_impl.cc
+++ b/gd/security/internal/security_manager_impl.cc
@@ -1,4 +1,4 @@
-/******************************************************************************
+/*
  *
  *  Copyright 2019 The Android Open Source Project
  *
@@ -14,88 +14,96 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- ******************************************************************************/
+ */
 #include "security_manager_impl.h"
 
 #include <iostream>
-#include <unordered_map>
 
+#include "hci/address_with_type.h"
 #include "os/log.h"
-#include "security/pairing/classic_pairing_handler.h"
 #include "security/security_manager.h"
 
-using namespace bluetooth::security::internal;
-using bluetooth::hci::Device;
-using bluetooth::hci::DeviceType;
-using bluetooth::security::ISecurityManagerListener;
-using bluetooth::security::pairing::PairingHandler;
+namespace bluetooth {
+namespace security {
+namespace internal {
 
-namespace {
-std::unordered_map<std::shared_ptr<Device>, std::unique_ptr<PairingHandler>> pairing_handler_map_;
+std::shared_ptr<bluetooth::security::record::SecurityRecord> SecurityManagerImpl::CreateSecurityRecord(
+    hci::Address address) {
+  hci::AddressWithType device(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS);
+  // Security record check
+  auto entry = security_record_map_.find(device.GetAddress());
+  if (entry == security_record_map_.end()) {
+    LOG_INFO("No security record for device: %s ", device.ToString().c_str());
+    // Create one
+    std::shared_ptr<security::record::SecurityRecord> record =
+        std::make_shared<security::record::SecurityRecord>(device);
+    auto new_entry = std::pair<hci::Address, std::shared_ptr<security::record::SecurityRecord>>(
+        record->GetDevice().GetAddress(), record);
+    // Keep track of it
+    security_record_map_.insert(new_entry);
+    return record;
+  }
+  return entry->second;
+}
 
-void dispatch_new_pairing_handler(std::shared_ptr<bluetooth::security::record::SecurityRecord> record) {
-  auto entry = pairing_handler_map_.find(record->GetDevice());
+void SecurityManagerImpl::DispatchPairingHandler(std::shared_ptr<security::record::SecurityRecord> record,
+                                                 bool locally_initiated) {
+  common::OnceCallback<void(hci::Address)> callback =
+      common::BindOnce(&SecurityManagerImpl::OnPairingHandlerComplete, common::Unretained(this));
+  auto entry = pairing_handler_map_.find(record->GetDevice().GetAddress());
   if (entry != pairing_handler_map_.end()) {
     LOG_WARN("Device already has a pairing handler, and is in the middle of pairing!");
     return;
   }
-  std::unique_ptr<PairingHandler> pairing_handler = nullptr;
-  switch (record->GetDevice()->GetDeviceType()) {
-    case DeviceType::CLASSIC:
-      pairing_handler = std::make_unique<bluetooth::security::pairing::ClassicPairingHandler>(record);
+  std::shared_ptr<pairing::PairingHandler> pairing_handler = nullptr;
+  switch (record->GetDevice().GetAddressType()) {
+    case hci::AddressType::PUBLIC_DEVICE_ADDRESS:
+      pairing_handler = std::make_shared<security::pairing::ClassicPairingHandler>(
+          l2cap_classic_module_->GetFixedChannelManager(), security_manager_channel_, record, security_handler_,
+          std::move(callback));
       break;
     default:
-      ASSERT_LOG(false, "Pairing type %d not implemented!", record->GetDevice()->GetDeviceType());
+      ASSERT_LOG(false, "Pairing type %hhu not implemented!", record->GetDevice().GetAddressType());
   }
-  auto new_entry = std::pair<std::shared_ptr<Device>, std::unique_ptr<PairingHandler>>(record->GetDevice(),
-                                                                                       std::move(pairing_handler));
+  auto new_entry = std::pair<hci::Address, std::shared_ptr<pairing::PairingHandler>>(record->GetDevice().GetAddress(),
+                                                                                     pairing_handler);
   pairing_handler_map_.insert(std::move(new_entry));
+  pairing_handler->Initiate(locally_initiated, pairing::kDefaultIoCapability, pairing::kDefaultOobDataPresent,
+                            pairing::kDefaultAuthenticationRequirements);
 }
-}  // namespace
 
 void SecurityManagerImpl::Init() {
+  security_manager_channel_->SetChannelListener(this);
+  security_manager_channel_->SendCommand(hci::WriteSimplePairingModeBuilder::Create(hci::Enable::ENABLED));
+  security_manager_channel_->SendCommand(hci::WriteSecureConnectionsHostSupportBuilder::Create(hci::Enable::ENABLED));
   // TODO(optedoblivion): Populate security record memory map from disk
-  //  security_manager_channel_->SetChannelListener(this);
 }
 
-void SecurityManagerImpl::CreateBond(std::shared_ptr<hci::ClassicDevice> device) {
-  std::string uuid = device->GetUuid();
-  // Security record check
-  //  if (device_database_->GetDeviceById(uuid) != nullptr) {
-  //    LOG_WARN("Device already exists in the database");
-  // TODO(optedoblivion): Check security record if device is already bonded
-  // if no security record, need to initiate bonding
-  // if security record and not bonded, need to initiate bonding
-  // if security record and is bonded, then do nothing
-  //  }
-
-  // device_database_->AddDevice(device);
-  // Create security record
-  // Pass to pairing handler
-  std::shared_ptr<record::SecurityRecord> record = std::make_shared<record::SecurityRecord>(device);
-  dispatch_new_pairing_handler(record);
-  // init the pairing handler
-  // Update bonded flag on security record
-  // Update bonded flag on device to BONDING (pairing handler does this)
-}
-
-void SecurityManagerImpl::CancelBond(std::shared_ptr<hci::ClassicDevice> device) {
-  auto entry = pairing_handler_map_.find(device);
-  if (entry != pairing_handler_map_.end()) {
-    pairing_handler_map_.erase(device);
+void SecurityManagerImpl::CreateBond(hci::AddressWithType device) {
+  auto record = CreateSecurityRecord(device.GetAddress());
+  if (record->IsBonded()) {
+    NotifyDeviceBonded(device);
+  } else {
+    // Dispatch pairing handler, if we are calling create we are the initiator
+    DispatchPairingHandler(record, true);
   }
-  // Remove from DB
-  // device_database_->RemoveDevice(device);
-  // Remove from map, no longer will the event queue use it
-  // If currently bonding, cancel pairing handler job
-  // else, cancel fails
 }
 
-void SecurityManagerImpl::RemoveBond(std::shared_ptr<hci::ClassicDevice> device) {
+void SecurityManagerImpl::CancelBond(hci::AddressWithType device) {
+  auto entry = pairing_handler_map_.find(device.GetAddress());
+  if (entry != pairing_handler_map_.end()) {
+    pairing_handler_map_.erase(entry);
+    entry->second->Cancel();
+  }
+}
+
+void SecurityManagerImpl::RemoveBond(hci::AddressWithType device) {
   CancelBond(device);
-  // Update bonded flag on device to UNBONDED
+  auto entry = security_record_map_.find(device.GetAddress());
+  if (entry != security_record_map_.end()) {
+    security_record_map_.erase(entry);
+  }
   // Signal disconnect
-  // Signal unbonding
   // Remove security record
   // Signal Remove from database
 }
@@ -140,3 +148,82 @@
         common::Bind(&ISecurityManagerListener::OnDeviceUnbonded, common::Unretained(iter.first), device));
   }
 }
+
+template <class T>
+void SecurityManagerImpl::HandleEvent(T packet) {
+  ASSERT(packet.IsValid());
+  auto entry = pairing_handler_map_.find(packet.GetBdAddr());
+  if (entry != pairing_handler_map_.end()) {
+    entry->second->OnReceive(packet);
+  } else {
+    auto event = hci::EventPacketView::Create(std::move(packet));
+    ASSERT_LOG(event.IsValid(), "Received invalid packet");
+    const hci::EventCode code = event.GetEventCode();
+    auto record = CreateSecurityRecord(packet.GetBdAddr());
+    switch (code) {
+      case hci::EventCode::LINK_KEY_REQUEST:
+        DispatchPairingHandler(record, true);
+        break;
+      default:
+        LOG_ERROR("No classic pairing handler for device '%s' ready for command '%hhx' ",
+                  packet.GetBdAddr().ToString().c_str(), packet.GetEventCode());
+        break;
+    }
+  }
+}
+
+void SecurityManagerImpl::OnHciEventReceived(hci::EventPacketView packet) {
+  auto event = hci::EventPacketView::Create(packet);
+  ASSERT_LOG(event.IsValid(), "Received invalid packet");
+  const hci::EventCode code = event.GetEventCode();
+  switch (code) {
+    case hci::EventCode::PIN_CODE_REQUEST:
+      HandleEvent<hci::PinCodeRequestView>(hci::PinCodeRequestView::Create(event));
+      break;
+    case hci::EventCode::LINK_KEY_REQUEST:
+      HandleEvent(hci::LinkKeyRequestView::Create(event));
+      break;
+    case hci::EventCode::LINK_KEY_NOTIFICATION:
+      HandleEvent(hci::LinkKeyNotificationView::Create(event));
+      break;
+    case hci::EventCode::IO_CAPABILITY_REQUEST:
+      HandleEvent(hci::IoCapabilityRequestView::Create(event));
+      break;
+    case hci::EventCode::IO_CAPABILITY_RESPONSE:
+      HandleEvent(hci::IoCapabilityResponseView::Create(event));
+      break;
+    case hci::EventCode::SIMPLE_PAIRING_COMPLETE:
+      HandleEvent(hci::SimplePairingCompleteView::Create(event));
+      break;
+    case hci::EventCode::REMOTE_OOB_DATA_REQUEST:
+      HandleEvent(hci::RemoteOobDataRequestView::Create(event));
+      break;
+    case hci::EventCode::USER_PASSKEY_NOTIFICATION:
+      HandleEvent<hci::UserPasskeyNotificationView>(hci::UserPasskeyNotificationView::Create(event));
+      break;
+    case hci::EventCode::KEYPRESS_NOTIFICATION:
+      HandleEvent(hci::KeypressNotificationView::Create(event));
+      break;
+    case hci::EventCode::USER_CONFIRMATION_REQUEST:
+      HandleEvent(hci::UserConfirmationRequestView::Create(event));
+      break;
+    case hci::EventCode::USER_PASSKEY_REQUEST:
+      HandleEvent(hci::UserPasskeyRequestView::Create(event));
+      break;
+    default:
+      ASSERT_LOG(false, "Cannot handle received packet: %s", hci::EventCodeText(code).c_str());
+      break;
+  }
+}
+
+void SecurityManagerImpl::OnPairingHandlerComplete(hci::Address address) {
+  auto entry = pairing_handler_map_.find(address);
+  if (entry != pairing_handler_map_.end()) {
+    pairing_handler_map_.erase(entry);
+  }
+  NotifyDeviceBonded(hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS));
+}
+
+}  // namespace internal
+}  // namespace security
+}  // namespace bluetooth
diff --git a/gd/security/internal/security_manager_impl.h b/gd/security/internal/security_manager_impl.h
index d6768c9..fc43935 100644
--- a/gd/security/internal/security_manager_impl.h
+++ b/gd/security/internal/security_manager_impl.h
@@ -16,13 +16,16 @@
 
 #pragma once
 
+#include <unordered_map>
+#include <utility>
+
 #include "hci/classic_device.h"
 #include "l2cap/classic/l2cap_classic_module.h"
 #include "l2cap/le/l2cap_le_module.h"
 #include "os/handler.h"
 #include "security/channel/security_manager_channel.h"
-
-#include <utility>
+#include "security/pairing/classic_pairing_handler.h"
+#include "security/record/security_record.h"
 
 namespace bluetooth {
 namespace security {
@@ -31,7 +34,7 @@
 
 namespace internal {
 
-class SecurityManagerImpl /*: public channel::ISecurityManagerChannelListener*/ {
+class SecurityManagerImpl : public channel::ISecurityManagerChannelListener {
  public:
   explicit SecurityManagerImpl(os::Handler* security_handler, l2cap::le::L2capLeModule* l2cap_le_module,
                                l2cap::classic::L2capClassicModule* l2cap_classic_module,
@@ -53,7 +56,7 @@
    * @param device pointer to device we want to bond with
    * @return true if bonded or pairing started successfully, false if currently pairing
    */
-  void CreateBond(std::shared_ptr<hci::ClassicDevice> device);
+  void CreateBond(hci::AddressWithType device);
 
   /* void CreateBond(std::shared_ptr<hci::LeDevice> device); */
 
@@ -63,7 +66,7 @@
    * @param device pointer to device with which we want to cancel our bond
    * @return <code>true</code> if successfully stopped
    */
-  void CancelBond(std::shared_ptr<bluetooth::hci::ClassicDevice> device);
+  void CancelBond(hci::AddressWithType device);
 
   /* void CancelBond(std::shared_ptr<hci::LeDevice> device); */
 
@@ -73,7 +76,7 @@
    * @param device pointer to device we want to forget
    * @return true if removed
    */
-  void RemoveBond(std::shared_ptr<bluetooth::hci::ClassicDevice> device);
+  void RemoveBond(hci::AddressWithType device);
 
   /* void RemoveBond(std::shared_ptr<hci::LeDevice> device); */
 
@@ -91,33 +94,30 @@
    */
   void UnregisterCallbackListener(ISecurityManagerListener* listener);
 
+  // ISecurityManagerChannel
+  void OnHciEventReceived(hci::EventPacketView packet) override;
+
+  void OnPairingHandlerComplete(hci::Address address);
+
  protected:
   std::vector<std::pair<ISecurityManagerListener*, os::Handler*>> listeners_;
   void NotifyDeviceBonded(hci::AddressWithType device);
   void NotifyDeviceBondFailed(hci::AddressWithType device);
   void NotifyDeviceUnbonded(hci::AddressWithType device);
 
-  // ISecurityManagerChannel
-  void OnChangeConnectionLinkKeyComplete(std::shared_ptr<hci::Device> device,
-                                         hci::ChangeConnectionLinkKeyCompleteView packet);
-  void OnMasterLinkKeyComplete(std::shared_ptr<hci::Device> device, hci::MasterLinkKeyCompleteView packet);
-  void OnPinCodeRequest(std::shared_ptr<hci::Device> device, hci::PinCodeRequestView packet);
-  void OnLinkKeyRequest(std::shared_ptr<hci::Device> device, hci::LinkKeyRequestView packet);
-  void OnLinkKeyNotification(std::shared_ptr<hci::Device> device, hci::LinkKeyNotificationView packet);
-  void OnIoCapabilityRequest(std::shared_ptr<hci::Device> device, hci::IoCapabilityRequestView packet);
-  void OnIoCapabilityResponse(std::shared_ptr<hci::Device> device, hci::IoCapabilityResponseView packet);
-  void OnSimplePairingComplete(std::shared_ptr<hci::Device> device, hci::SimplePairingCompleteView packet);
-  void OnReturnLinkKeys(std::shared_ptr<hci::Device> device, hci::ReturnLinkKeysView packet);
-  void OnEncryptionChange(std::shared_ptr<hci::Device> device, hci::EncryptionChangeView packet);
-  void OnEncryptionKeyRefreshComplete(std::shared_ptr<hci::Device> device,
-                                      hci::EncryptionKeyRefreshCompleteView packet);
-  void OnRemoteOobDataRequest(std::shared_ptr<hci::Device> device, hci::RemoteOobDataRequestView packet);
-
  private:
+  template <class T>
+  void HandleEvent(T packet);
+
+  std::shared_ptr<record::SecurityRecord> CreateSecurityRecord(hci::Address address);
+  void DispatchPairingHandler(std::shared_ptr<record::SecurityRecord> record, bool locally_initiated);
+
   os::Handler* security_handler_ __attribute__((unused));
   l2cap::le::L2capLeModule* l2cap_le_module_ __attribute__((unused));
   l2cap::classic::L2capClassicModule* l2cap_classic_module_ __attribute__((unused));
   channel::SecurityManagerChannel* security_manager_channel_ __attribute__((unused));
+  std::unordered_map<hci::Address, std::shared_ptr<record::SecurityRecord>> security_record_map_;
+  std::unordered_map<hci::Address, std::shared_ptr<pairing::PairingHandler>> pairing_handler_map_;
 };
 }  // namespace internal
 }  // namespace security
diff --git a/gd/security/pairing/Android.bp b/gd/security/pairing/Android.bp
new file mode 100644
index 0000000..350c10e
--- /dev/null
+++ b/gd/security/pairing/Android.bp
@@ -0,0 +1,13 @@
+filegroup {
+    name: "BluetoothSecurityPairingSources",
+    srcs: [
+        "classic_pairing_handler.cc",
+    ]
+}
+
+filegroup {
+    name: "BluetoothSecurityPairingTestSources",
+    srcs: [
+        "classic_pairing_handler_unittest.cc",
+    ]
+}
diff --git a/gd/security/pairing/classic_pairing_handler.cc b/gd/security/pairing/classic_pairing_handler.cc
new file mode 100644
index 0000000..e854efe
--- /dev/null
+++ b/gd/security/pairing/classic_pairing_handler.cc
@@ -0,0 +1,343 @@
+/*
+ *
+ *  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.
+ *
+ */
+#include "security/pairing/classic_pairing_handler.h"
+
+namespace bluetooth {
+namespace security {
+namespace pairing {
+
+void ClassicPairingHandler::OnRegistrationComplete(
+    l2cap::classic::FixedChannelManager::RegistrationResult result,
+    std::unique_ptr<l2cap::classic::FixedChannelService> fixed_channel_service) {
+  fixed_channel_service_ = std::move(fixed_channel_service);
+  fixed_channel_manager_->ConnectServices(
+      GetRecord()->GetDevice().GetAddress(),
+      common::Bind(&ClassicPairingHandler::OnConnectionFail, common::Unretained(this)), security_handler_);
+}
+
+void ClassicPairingHandler::OnUnregistered() {
+  std::move(complete_callback_).Run(GetRecord()->GetDevice().GetAddress());
+}
+
+void ClassicPairingHandler::OnConnectionOpen(std::unique_ptr<l2cap::classic::FixedChannel> fixed_channel) {
+  ASSERT(fixed_channel_ == nullptr);
+  fixed_channel_ = std::move(fixed_channel);
+  fixed_channel_->Acquire();
+  fixed_channel_->RegisterOnCloseCallback(
+      security_handler_, common::BindOnce(&ClassicPairingHandler::OnConnectionClose, common::Unretained(this)));
+}
+
+void ClassicPairingHandler::OnConnectionFail(l2cap::classic::FixedChannelManager::ConnectionResult result) {
+  Cancel();
+}
+void ClassicPairingHandler::OnConnectionClose(hci::ErrorCode error_code) {
+  // Called when the connection gets closed
+  LOG_ERROR("Connection closed due to: %s", hci::ErrorCodeText(error_code).c_str());
+  ASSERT(fixed_channel_ != nullptr);
+  Cancel();
+}
+
+void ClassicPairingHandler::Initiate(bool locally_initiated, hci::IoCapability io_capability,
+                                     hci::OobDataPresent oob_present,
+                                     hci::AuthenticationRequirements auth_requirements) {
+  locally_initiated_ = locally_initiated;
+  local_io_capability_ = io_capability;
+  local_oob_present_ = oob_present;
+  local_authentication_requirements_ = auth_requirements;
+
+  // TODO(optedoblivion): Read OOB data
+  // if host and controller support secure connections used HCIREADLOCALOOBEXTENDEDDATA vs HCIREADLOCALOOBDATA
+
+  fixed_channel_manager_->RegisterService(
+      l2cap::kClassicPairingTriggerCid, security_policy_,
+      common::Bind(&ClassicPairingHandler::OnRegistrationComplete, common::Unretained(this)),
+      common::Bind(&ClassicPairingHandler::OnConnectionOpen, common::Unretained(this)), security_handler_);
+}
+
+void ClassicPairingHandler::Cancel() {
+  if (fixed_channel_ != nullptr) {
+    fixed_channel_->Release();
+  }
+  if (fixed_channel_service_ != nullptr) {
+    fixed_channel_service_->Unregister(common::Bind(&ClassicPairingHandler::OnUnregistered, common::Unretained(this)),
+                                       security_handler_);
+  }
+}
+
+void ClassicPairingHandler::OnReceive(hci::ChangeConnectionLinkKeyCompleteView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received unsupported event: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+}
+
+void ClassicPairingHandler::OnReceive(hci::MasterLinkKeyCompleteView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received unsupported event: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+}
+
+void ClassicPairingHandler::OnReceive(hci::PinCodeRequestView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+  ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
+}
+
+void ClassicPairingHandler::OnReceive(hci::LinkKeyRequestView packet) {
+  ASSERT(packet.IsValid());
+  // TODO(optedoblivion): Add collision detection here
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+  ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
+  if (GetRecord()->IsBonded() || GetRecord()->IsPaired()) {
+    auto packet =
+        hci::LinkKeyRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress(), GetRecord()->GetLinkKey());
+    this->GetChannel()->SendCommand(std::move(packet));
+  } else {
+    auto packet = hci::LinkKeyRequestNegativeReplyBuilder::Create(GetRecord()->GetDevice().GetAddress());
+    this->GetChannel()->SendCommand(std::move(packet));
+  }
+}
+
+void ClassicPairingHandler::OnReceive(hci::LinkKeyNotificationView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+  ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
+  GetRecord()->SetLinkKey(packet.GetLinkKey(), packet.GetKeyType());
+}
+
+void ClassicPairingHandler::OnReceive(hci::IoCapabilityRequestView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+  ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
+  hci::IoCapability io_capability = local_io_capability_;
+  hci::OobDataPresent oob_present = hci::OobDataPresent::NOT_PRESENT;
+  hci::AuthenticationRequirements authentication_requirements = local_authentication_requirements_;
+  auto reply_packet = hci::IoCapabilityRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress(), io_capability,
+                                                                   oob_present, authentication_requirements);
+  this->GetChannel()->SendCommand(std::move(reply_packet));
+}
+
+void ClassicPairingHandler::OnReceive(hci::IoCapabilityResponseView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+  ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
+
+  // Using local variable until device database pointer is ready
+  remote_io_capability_ = packet.GetIoCapability();
+  // TODO(optedoblivion): device->SetIoCapability(packet.GetIoCapability);
+}
+
+void ClassicPairingHandler::OnReceive(hci::SimplePairingCompleteView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+  ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
+  Cancel();
+}
+
+void ClassicPairingHandler::OnReceive(hci::ReturnLinkKeysView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+}
+
+void ClassicPairingHandler::OnReceive(hci::EncryptionChangeView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+}
+
+void ClassicPairingHandler::OnReceive(hci::EncryptionKeyRefreshCompleteView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+}
+
+void ClassicPairingHandler::OnReceive(hci::RemoteOobDataRequestView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+  ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
+}
+
+void ClassicPairingHandler::OnReceive(hci::UserPasskeyNotificationView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+  ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
+}
+
+void ClassicPairingHandler::OnReceive(hci::KeypressNotificationView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+  LOG_INFO("Notification Type: %s", hci::KeypressNotificationTypeText(packet.GetNotificationType()).c_str());
+  switch (packet.GetNotificationType()) {
+    case hci::KeypressNotificationType::ENTRY_STARTED:
+      // Get ready to keep track of key input
+      break;
+    case hci::KeypressNotificationType::DIGIT_ENTERED:
+      // Append digit to key
+      break;
+    case hci::KeypressNotificationType::DIGIT_ERASED:
+      // erase last digit from key
+      break;
+    case hci::KeypressNotificationType::CLEARED:
+      // erase all digits from key
+      break;
+    case hci::KeypressNotificationType::ENTRY_COMPLETED:
+      // set full key to security record
+      break;
+  }
+}
+
+/**
+ * Here we decide what type of pairing authentication method we will use
+ *
+ * The table is on pg 2133 of the Core v5.1 spec.
+ */
+void ClassicPairingHandler::OnReceive(hci::UserConfirmationRequestView packet) {
+  ASSERT(packet.IsValid());
+  LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
+  ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
+  // if locally_initialized, use default, otherwise us remote io caps
+  hci::IoCapability initiator_io_capability = (locally_initiated_) ? local_io_capability_ : remote_io_capability_;
+  hci::IoCapability responder_io_capability = (!locally_initiated_) ? local_io_capability_ : remote_io_capability_;
+  // TODO(optedoblivion): Check for TEMPORARY pairing case
+  switch (initiator_io_capability) {
+    case hci::IoCapability::DISPLAY_ONLY:
+      switch (responder_io_capability) {
+        case hci::IoCapability::DISPLAY_ONLY:
+          // NumericComparison, Both auto confirm
+          LOG_INFO("Numeric Comparison: A and B auto confirm");
+          GetChannel()->SendCommand(
+              hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
+          // Unauthenticated
+          break;
+        case hci::IoCapability::DISPLAY_YES_NO:
+          // NumericComparison, Initiator auto confirm, Responder display
+          GetChannel()->SendCommand(
+              hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
+          LOG_INFO("Numeric Comparison: A auto confirm");
+          // Unauthenticated
+          break;
+        case hci::IoCapability::KEYBOARD_ONLY:
+          // PassKey Entry, Initiator display, Responder input
+          // TODO(optedoblivion): Notify UI
+          LOG_INFO("Notify UI");
+          // Authenticated
+          break;
+        case hci::IoCapability::NO_INPUT_NO_OUTPUT:
+          // NumericComparison, Both auto confirm
+          LOG_INFO("Numeric Comparison: A and B auto confirm");
+          GetChannel()->SendCommand(
+              hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
+          // Unauthenticated
+          break;
+      }
+      break;
+    case hci::IoCapability::DISPLAY_YES_NO:
+      switch (responder_io_capability) {
+        case hci::IoCapability::DISPLAY_ONLY:
+          // NumericComparison, Initiator display, Responder auto confirm
+          // TODO(optedoblivion): Notify UI
+          LOG_INFO("Notify UI");
+          // Unauthenticated
+          break;
+        case hci::IoCapability::DISPLAY_YES_NO:
+          // NumericComparison Both Display, Both confirm
+          // TODO(optedoblivion): Notify UI
+          LOG_INFO("Notify UI");
+          // Authenticated
+          break;
+        case hci::IoCapability::KEYBOARD_ONLY:
+          // PassKey Entry, Initiator display, Responder input
+          // TODO(optedoblivion): Notify UI
+          LOG_INFO("Notify UI");
+          // Authenticated
+          break;
+        case hci::IoCapability::NO_INPUT_NO_OUTPUT:
+          // NumericComparison, auto confirm Responder, Yes/No confirm Initiator. Don't show confirmation value
+          // TODO(optedoblivion): Notify UI
+          LOG_INFO("Notify UI");
+          // Unauthenticated
+          break;
+      }
+      break;
+    case hci::IoCapability::KEYBOARD_ONLY:
+      switch (responder_io_capability) {
+        case hci::IoCapability::DISPLAY_ONLY:
+          // PassKey Entry, Responder display, Initiator input
+          // TODO(optedoblivion): Notify UI
+          LOG_INFO("Notify UI");
+          // Authenticated
+          break;
+        case hci::IoCapability::DISPLAY_YES_NO:
+          // PassKey Entry, Responder display, Initiator input
+          // TODO(optedoblivion): Notify UI
+          LOG_INFO("Notify UI");
+          // Authenticated
+          break;
+        case hci::IoCapability::KEYBOARD_ONLY:
+          // PassKey Entry, both input
+          // TODO(optedoblivion): Notify UI
+          LOG_INFO("Notify UI");
+          // Authenticated
+          break;
+        case hci::IoCapability::NO_INPUT_NO_OUTPUT:
+          // NumericComparison, both auto confirm
+          LOG_INFO("Numeric Comparison: A and B auto confirm");
+          GetChannel()->SendCommand(
+              hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
+          // Unauthenticated
+          break;
+      }
+      break;
+    case hci::IoCapability::NO_INPUT_NO_OUTPUT:
+      switch (responder_io_capability) {
+        case hci::IoCapability::DISPLAY_ONLY:
+          // NumericComparison, both auto confirm
+          LOG_INFO("Numeric Comparison: A and B auto confirm");
+          GetChannel()->SendCommand(
+              hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
+          // Unauthenticated
+          break;
+        case hci::IoCapability::DISPLAY_YES_NO:
+          // NumericComparison, Initiator auto confirm, Responder Yes/No confirm, no show conf val
+          LOG_INFO("Numeric Comparison: A auto confirm");
+          GetChannel()->SendCommand(
+              hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
+          // Unauthenticated
+          break;
+        case hci::IoCapability::KEYBOARD_ONLY:
+          // NumericComparison, both auto confirm
+          LOG_INFO("Numeric Comparison: A and B auto confirm");
+          GetChannel()->SendCommand(
+              hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
+          // Unauthenticated
+          break;
+        case hci::IoCapability::NO_INPUT_NO_OUTPUT:
+          // NumericComparison, both auto confirm
+          LOG_INFO("Numeric Comparison: A and B auto confirm");
+          GetChannel()->SendCommand(
+              hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
+          // Unauthenticated
+          break;
+      }
+      break;
+  }
+}
+
+void ClassicPairingHandler::OnReceive(hci::UserPasskeyRequestView packet) {
+  ASSERT(packet.IsValid());
+  ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
+}
+
+}  // namespace pairing
+}  // namespace security
+}  // namespace bluetooth
\ No newline at end of file
diff --git a/gd/security/pairing/classic_pairing_handler.h b/gd/security/pairing/classic_pairing_handler.h
index fc8eed4..f8a9d39 100644
--- a/gd/security/pairing/classic_pairing_handler.h
+++ b/gd/security/pairing/classic_pairing_handler.h
@@ -1,4 +1,4 @@
-/******************************************************************************
+/*
  *
  *  Copyright 2019 The Android Open Source Project
  *
@@ -14,27 +14,79 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- ******************************************************************************/
+ */
 #pragma once
 
-#include "pairing_handler.h"
+#include "security/pairing/pairing_handler.h"
 
-#include "security/smp_packets.h"
+#include <utility>
 
-using namespace bluetooth::security::pairing;
+#include "l2cap/classic/l2cap_classic_module.h"
 
 namespace bluetooth {
 namespace security {
 namespace pairing {
 
+static constexpr hci::IoCapability kDefaultIoCapability = hci::IoCapability::DISPLAY_YES_NO;
+static constexpr hci::OobDataPresent kDefaultOobDataPresent = hci::OobDataPresent::NOT_PRESENT;
+static constexpr hci::AuthenticationRequirements kDefaultAuthenticationRequirements =
+    hci::AuthenticationRequirements::DEDICATED_BONDING_MITM_PROTECTION;
+
 class ClassicPairingHandler : public PairingHandler {
  public:
-  explicit ClassicPairingHandler(std::shared_ptr<record::SecurityRecord> record) : PairingHandler(record) {}
+  ClassicPairingHandler(std::shared_ptr<l2cap::classic::FixedChannelManager> fixed_channel_manager,
+                        channel::SecurityManagerChannel* security_manager_channel,
+                        std::shared_ptr<record::SecurityRecord> record, os::Handler* security_handler,
+                        common::OnceCallback<void(hci::Address)> complete_callback)
+      : PairingHandler(security_manager_channel, std::move(record)),
+        fixed_channel_manager_(std::move(fixed_channel_manager)), security_policy_(),
+        security_handler_(security_handler), remote_io_capability_(kDefaultIoCapability),
+        local_io_capability_(kDefaultIoCapability), local_oob_present_(kDefaultOobDataPresent),
+        local_authentication_requirements_(kDefaultAuthenticationRequirements),
+        complete_callback_(std::move(complete_callback)) {}
 
-  void Init() {
-    // Set auth required
-    // Connect to device
-  }
+  ~ClassicPairingHandler() override = default;
+
+  void Initiate(bool locally_initiated, hci::IoCapability io_capability, hci::OobDataPresent oob_present,
+                hci::AuthenticationRequirements auth_requirements) override;
+  void Cancel() override;
+
+  void OnReceive(hci::ChangeConnectionLinkKeyCompleteView packet) override;
+  void OnReceive(hci::MasterLinkKeyCompleteView packet) override;
+  void OnReceive(hci::PinCodeRequestView packet) override;
+  void OnReceive(hci::LinkKeyRequestView packet) override;
+  void OnReceive(hci::LinkKeyNotificationView packet) override;
+  void OnReceive(hci::IoCapabilityRequestView packet) override;
+  void OnReceive(hci::IoCapabilityResponseView packet) override;
+  void OnReceive(hci::SimplePairingCompleteView packet) override;
+  void OnReceive(hci::ReturnLinkKeysView packet) override;
+  void OnReceive(hci::EncryptionChangeView packet) override;
+  void OnReceive(hci::EncryptionKeyRefreshCompleteView packet) override;
+  void OnReceive(hci::RemoteOobDataRequestView packet) override;
+  void OnReceive(hci::UserPasskeyNotificationView packet) override;
+  void OnReceive(hci::KeypressNotificationView packet) override;
+  void OnReceive(hci::UserConfirmationRequestView packet) override;
+  void OnReceive(hci::UserPasskeyRequestView packet) override;
+
+ private:
+  void OnRegistrationComplete(l2cap::classic::FixedChannelManager::RegistrationResult result,
+                              std::unique_ptr<l2cap::classic::FixedChannelService> fixed_channel_service);
+  void OnUnregistered();
+  void OnConnectionOpen(std::unique_ptr<l2cap::classic::FixedChannel> fixed_channel);
+  void OnConnectionFail(l2cap::classic::FixedChannelManager::ConnectionResult result);
+  void OnConnectionClose(hci::ErrorCode error_code);
+
+  std::shared_ptr<l2cap::classic::FixedChannelManager> fixed_channel_manager_;
+  std::unique_ptr<l2cap::classic::FixedChannelService> fixed_channel_service_{nullptr};
+  l2cap::SecurityPolicy security_policy_ __attribute__((unused));
+  os::Handler* security_handler_ __attribute__((unused));
+  hci::IoCapability remote_io_capability_ __attribute__((unused));
+  hci::IoCapability local_io_capability_ __attribute__((unused));
+  hci::OobDataPresent local_oob_present_ __attribute__((unused));
+  hci::AuthenticationRequirements local_authentication_requirements_ __attribute__((unused));
+  std::unique_ptr<l2cap::classic::FixedChannel> fixed_channel_{nullptr};
+  common::OnceCallback<void(hci::Address)> complete_callback_;
+  bool locally_initiated_ = false;
 };
 
 }  // namespace pairing
diff --git a/gd/security/pairing/classic_pairing_handler_unittest.cc b/gd/security/pairing/classic_pairing_handler_unittest.cc
new file mode 100644
index 0000000..9266303
--- /dev/null
+++ b/gd/security/pairing/classic_pairing_handler_unittest.cc
@@ -0,0 +1,503 @@
+/*
+ *
+ *  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.
+ *
+ */
+#include "security/pairing/classic_pairing_handler.h"
+
+#include <gtest/gtest.h>
+#include <memory>
+
+#include "hci/hci_packets.h"
+#include "l2cap/classic/fixed_channel_manager_mock.h"
+#include "packet/raw_builder.h"
+#include "security/channel/security_manager_channel.h"
+#include "security/smp_packets.h"
+#include "security/test/fake_hci_layer.h"
+
+namespace bluetooth {
+namespace security {
+namespace channel {
+namespace {
+
+using bluetooth::security::channel::SecurityManagerChannel;
+using hci::Address;
+using hci::AuthenticationRequirements;
+using hci::CommandCompleteBuilder;
+using hci::IoCapabilityRequestReplyBuilder;
+using hci::IoCapabilityRequestView;
+using hci::OobDataPresent;
+using hci::OpCode;
+using os::Handler;
+using os::Thread;
+using packet::RawBuilder;
+
+class SecurityManagerChannelCallback : public ISecurityManagerChannelListener {
+ public:
+  explicit SecurityManagerChannelCallback(pairing::ClassicPairingHandler* pairing_handler)
+      : pairing_handler_(pairing_handler) {}
+  void OnHciEventReceived(hci::EventPacketView packet) override {
+    auto event = hci::EventPacketView::Create(packet);
+    ASSERT_LOG(event.IsValid(), "Received invalid packet");
+    const hci::EventCode code = event.GetEventCode();
+    switch (code) {
+      case hci::EventCode::PIN_CODE_REQUEST:
+        pairing_handler_->OnReceive(hci::PinCodeRequestView::Create(event));
+        break;
+      case hci::EventCode::LINK_KEY_REQUEST:
+        pairing_handler_->OnReceive(hci::LinkKeyRequestView::Create(event));
+        break;
+      case hci::EventCode::LINK_KEY_NOTIFICATION:
+        pairing_handler_->OnReceive(hci::LinkKeyNotificationView::Create(event));
+        break;
+      case hci::EventCode::IO_CAPABILITY_REQUEST:
+        pairing_handler_->OnReceive(hci::IoCapabilityRequestView::Create(event));
+        break;
+      case hci::EventCode::IO_CAPABILITY_RESPONSE:
+        pairing_handler_->OnReceive(hci::IoCapabilityResponseView::Create(event));
+        break;
+      case hci::EventCode::SIMPLE_PAIRING_COMPLETE:
+        pairing_handler_->OnReceive(hci::SimplePairingCompleteView::Create(event));
+        break;
+      case hci::EventCode::RETURN_LINK_KEYS:
+        pairing_handler_->OnReceive(hci::ReturnLinkKeysView::Create(event));
+        break;
+      case hci::EventCode::REMOTE_OOB_DATA_REQUEST:
+        pairing_handler_->OnReceive(hci::RemoteOobDataRequestView::Create(event));
+        break;
+      case hci::EventCode::USER_PASSKEY_NOTIFICATION:
+        pairing_handler_->OnReceive(hci::UserPasskeyNotificationView::Create(event));
+        break;
+      case hci::EventCode::KEYPRESS_NOTIFICATION:
+        pairing_handler_->OnReceive(hci::KeypressNotificationView::Create(event));
+        break;
+      case hci::EventCode::USER_CONFIRMATION_REQUEST:
+        pairing_handler_->OnReceive(hci::UserConfirmationRequestView::Create(event));
+        break;
+      case hci::EventCode::USER_PASSKEY_REQUEST:
+        pairing_handler_->OnReceive(hci::UserPasskeyRequestView::Create(event));
+        break;
+      default:
+        ASSERT_LOG(false, "Cannot handle received packet: %s", hci::EventCodeText(code).c_str());
+        break;
+    }
+  }
+
+ private:
+  pairing::ClassicPairingHandler* pairing_handler_ = nullptr;
+};
+
+static void pairing_complete_callback(bluetooth::hci::Address address) {}
+
+class ClassicPairingHandlerTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    handler_ = new Handler(&thread_);
+    hci_layer_ = new FakeHciLayer();
+    channel_ = new channel::SecurityManagerChannel(handler_, hci_layer_);
+    fake_registry_.InjectTestModule(&FakeHciLayer::Factory, hci_layer_);
+    fake_registry_.Start<FakeHciLayer>(&thread_);
+    security_record_ = std::make_shared<record::SecurityRecord>(device_);
+    std::shared_ptr<l2cap::classic::testing::MockFixedChannelManager> sptr =
+        std::shared_ptr<l2cap::classic::testing::MockFixedChannelManager>(
+            new l2cap::classic::testing::MockFixedChannelManager);
+    EXPECT_CALL(*sptr, RegisterService(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_))
+        .Times(::testing::AnyNumber());
+    pairing_handler_ = new pairing::ClassicPairingHandler(sptr, channel_, security_record_, handler_,
+                                                          common::Bind(&pairing_complete_callback));
+    channel_callback_ = new SecurityManagerChannelCallback(pairing_handler_);
+    channel_->SetChannelListener(channel_callback_);
+  }
+
+  void TearDown() override {
+    channel_->SetChannelListener(nullptr);
+    handler_->Clear();
+    fake_registry_.SynchronizeModuleHandler(&FakeHciLayer::Factory, std::chrono::milliseconds(20));
+    fake_registry_.StopAll();
+    delete pairing_handler_;
+    delete handler_;
+    delete channel_;
+    delete channel_callback_;
+  }
+
+  TestModuleRegistry fake_registry_;
+  Thread& thread_ = fake_registry_.GetTestThread();
+  Handler* handler_ = nullptr;
+  FakeHciLayer* hci_layer_ = nullptr;
+  hci::AddressWithType device_;
+  SecurityManagerChannelCallback* channel_callback_ = nullptr;
+  channel::SecurityManagerChannel* channel_ = nullptr;
+  pairing::ClassicPairingHandler* pairing_handler_ = nullptr;
+  std::shared_ptr<record::SecurityRecord> security_record_ = nullptr;
+};
+
+// Security Manager Boot Sequence (Required for SSP, these are already set at boot time)
+//  - WriteSimplePairingMode
+//  - WriteSecureConnectionsHostSupport
+//  - WriteAuthenticatedPayloadTimeout
+
+/*** Locally initiated ***/
+// Security Pairing Sequence (JustWorks)
+//  -> *Establish L2CAP connection*
+//  -> AuthenticationRequested (should L2CAP request secure service which causes this?)
+//  <- LinkKeyRequest
+//  -> LinkKeyRequestNegativeReply
+//  <- IoCapabilityRequest
+//  -> IoCapabilityRequestReply
+//  <- IoCapabilityResponse
+//  <- UserConfirmationRequest
+//  -> UserConfirmationRequestReply (auto)
+//  <- SimplePairingComplete
+//  <- LinkKeyNotification
+//  <- AuthenticationComplete
+//  -> SetConnectionEncryption
+//  <- EncryptionChange
+//  -> L2capConnectionResponse (if triggered by L2cap connection request)
+
+void ReceiveLinkKeyRequest(FakeHciLayer* hci_layer, hci::AddressWithType device) {
+  hci_layer->IncomingEvent(hci::LinkKeyRequestBuilder::Create(device.GetAddress()));
+}
+
+void ReceiveIoCapabilityRequest(FakeHciLayer* hci_layer, hci::AddressWithType device) {
+  hci_layer->IncomingEvent(hci::IoCapabilityRequestBuilder::Create(device.GetAddress()));
+}
+
+void ReceiveIoCapabilityResponse(FakeHciLayer* hci_layer, hci::AddressWithType device, hci::IoCapability io_cap,
+                                 hci::OobDataPresent oob_present, hci::AuthenticationRequirements auth_reqs) {
+  hci_layer->IncomingEvent(
+      hci::IoCapabilityResponseBuilder::Create(device.GetAddress(), io_cap, oob_present, auth_reqs));
+}
+
+void ReceiveUserConfirmationRequest(FakeHciLayer* hci_layer, hci::AddressWithType device, uint32_t numeric_value) {
+  hci_layer->IncomingEvent(hci::UserConfirmationRequestBuilder::Create(device.GetAddress(), numeric_value));
+}
+
+void ReceiveSimplePairingComplete(FakeHciLayer* hci_layer, hci::ErrorCode status, hci::AddressWithType device) {
+  hci_layer->IncomingEvent(hci::SimplePairingCompleteBuilder::Create(status, device.GetAddress()));
+}
+
+void ReceiveLinkKeyNotification(FakeHciLayer* hci_layer, hci::AddressWithType device, std::array<uint8_t, 16> link_key,
+                                hci::KeyType key_type) {
+  hci_layer->IncomingEvent(hci::LinkKeyNotificationBuilder::Create(device.GetAddress(), link_key, key_type));
+}
+
+hci::SecurityCommandView GetLastCommand(FakeHciLayer* hci_layer) {
+  auto last_command = std::move(hci_layer->GetLastCommand()->command);
+  auto command_packet = GetPacketView(std::move(last_command));
+  auto command_packet_view = hci::CommandPacketView::Create(command_packet);
+  ASSERT(command_packet_view.IsValid());
+  auto security_command_view = hci::SecurityCommandView::Create(command_packet_view);
+  ASSERT(security_command_view.IsValid());
+  return security_command_view;
+}
+
+TEST_F(ClassicPairingHandlerTest, setup_teardown) {}
+
+// display_only + display_only is JustWorks no confirmation
+// Needs dialog as per security a bug unless pairing is temporary
+TEST_F(ClassicPairingHandlerTest, locally_initiatied_display_only_display_only_temp) {
+  hci::IoCapability injected_io_capability = hci::IoCapability::DISPLAY_ONLY;
+  hci::AuthenticationRequirements injected_authentication_requirements = hci::AuthenticationRequirements::NO_BONDING;
+  pairing_handler_->Initiate(true, injected_io_capability, hci::OobDataPresent::NOT_PRESENT,
+                             injected_authentication_requirements);
+  ReceiveLinkKeyRequest(hci_layer_, device_);
+  auto security_command_view = GetLastCommand(hci_layer_);
+  auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view);
+  ASSERT_TRUE(link_key_neg_reply.IsValid());
+  ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode());
+  ReceiveIoCapabilityRequest(hci_layer_, device_);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(io_cap_request_reply.IsValid());
+  ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability());
+  ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent());
+  ASSERT_EQ(injected_authentication_requirements, io_cap_request_reply.GetAuthenticationRequirements());
+  ReceiveIoCapabilityResponse(hci_layer_, device_, hci::IoCapability::DISPLAY_ONLY, hci::OobDataPresent::NOT_PRESENT,
+                              hci::AuthenticationRequirements::NO_BONDING);
+  uint32_t numeric_value = 0x123;
+  ReceiveUserConfirmationRequest(hci_layer_, device_, numeric_value);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto user_conf_request_reply = hci::UserConfirmationRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(user_conf_request_reply.IsValid());
+  ReceiveSimplePairingComplete(hci_layer_, hci::ErrorCode::SUCCESS, device_);
+  std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
+  hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION;
+  ReceiveLinkKeyNotification(hci_layer_, device_, link_key, key_type);
+  ASSERT_EQ(link_key, security_record_->GetLinkKey());
+  ASSERT_EQ(key_type, security_record_->GetKeyType());
+}
+
+// display_only + display_yes_no is JustWorks no confirmation
+// Needs dialog as per security a bug unless pairing is temporary
+TEST_F(ClassicPairingHandlerTest, locally_initiatied_display_only_display_yes_no_temp) {
+  hci::IoCapability injected_io_capability = hci::IoCapability::DISPLAY_ONLY;
+  hci::AuthenticationRequirements injected_authentication_requirements = hci::AuthenticationRequirements::NO_BONDING;
+  pairing_handler_->Initiate(true, injected_io_capability, hci::OobDataPresent::NOT_PRESENT,
+                             injected_authentication_requirements);
+  ReceiveLinkKeyRequest(hci_layer_, device_);
+  auto security_command_view = GetLastCommand(hci_layer_);
+  auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view);
+  ASSERT_TRUE(link_key_neg_reply.IsValid());
+  ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode());
+  ReceiveIoCapabilityRequest(hci_layer_, device_);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(io_cap_request_reply.IsValid());
+  ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability());
+  ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent());
+  ASSERT_EQ(injected_authentication_requirements, io_cap_request_reply.GetAuthenticationRequirements());
+  ReceiveIoCapabilityResponse(hci_layer_, device_, hci::IoCapability::DISPLAY_YES_NO, hci::OobDataPresent::NOT_PRESENT,
+                              hci::AuthenticationRequirements::NO_BONDING);
+  uint32_t numeric_value = 0x123;
+  ReceiveUserConfirmationRequest(hci_layer_, device_, numeric_value);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto user_conf_request_reply = hci::UserConfirmationRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(user_conf_request_reply.IsValid());
+  ReceiveSimplePairingComplete(hci_layer_, hci::ErrorCode::SUCCESS, device_);
+  std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
+  hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION;
+  ReceiveLinkKeyNotification(hci_layer_, device_, link_key, key_type);
+  ASSERT_EQ(link_key, security_record_->GetLinkKey());
+  ASSERT_EQ(key_type, security_record_->GetKeyType());
+}
+
+// display_only + no_input_no_output is JustWorks no confirmation
+// Needs dialog as per security a bug unless pairing is temporary
+TEST_F(ClassicPairingHandlerTest, locally_initiatied_display_only_no_input_no_output_temp) {
+  hci::IoCapability injected_io_capability = hci::IoCapability::DISPLAY_ONLY;
+  hci::AuthenticationRequirements injected_authentication_requirements = hci::AuthenticationRequirements::NO_BONDING;
+  pairing_handler_->Initiate(true, injected_io_capability, hci::OobDataPresent::NOT_PRESENT,
+                             injected_authentication_requirements);
+  ReceiveLinkKeyRequest(hci_layer_, device_);
+  auto security_command_view = GetLastCommand(hci_layer_);
+  auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view);
+  ASSERT_TRUE(link_key_neg_reply.IsValid());
+  ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode());
+  ReceiveIoCapabilityRequest(hci_layer_, device_);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(io_cap_request_reply.IsValid());
+  ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability());
+  ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent());
+  ASSERT_EQ(injected_authentication_requirements, io_cap_request_reply.GetAuthenticationRequirements());
+  ReceiveIoCapabilityResponse(hci_layer_, device_, hci::IoCapability::NO_INPUT_NO_OUTPUT,
+                              hci::OobDataPresent::NOT_PRESENT, hci::AuthenticationRequirements::NO_BONDING);
+  uint32_t numeric_value = 0x123;
+  ReceiveUserConfirmationRequest(hci_layer_, device_, numeric_value);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto user_conf_request_reply = hci::UserConfirmationRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(user_conf_request_reply.IsValid());
+  ReceiveSimplePairingComplete(hci_layer_, hci::ErrorCode::SUCCESS, device_);
+  std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
+  hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION;
+  ReceiveLinkKeyNotification(hci_layer_, device_, link_key, key_type);
+  ASSERT_EQ(link_key, security_record_->GetLinkKey());
+  ASSERT_EQ(key_type, security_record_->GetKeyType());
+}
+
+// keyboard_only + no_input_no_output is JustWorks no confirmation
+// Needs dialog as per security a bug unless pairing is temporary
+TEST_F(ClassicPairingHandlerTest, locally_initiatied_keyboard_only_no_input_no_output_temp) {
+  hci::IoCapability injected_io_capability = hci::IoCapability::KEYBOARD_ONLY;
+  hci::AuthenticationRequirements injected_authentication_requirements = hci::AuthenticationRequirements::NO_BONDING;
+  pairing_handler_->Initiate(true, injected_io_capability, hci::OobDataPresent::NOT_PRESENT,
+                             injected_authentication_requirements);
+  ReceiveLinkKeyRequest(hci_layer_, device_);
+  auto security_command_view = GetLastCommand(hci_layer_);
+  auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view);
+  ASSERT_TRUE(link_key_neg_reply.IsValid());
+  ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode());
+  ReceiveIoCapabilityRequest(hci_layer_, device_);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(io_cap_request_reply.IsValid());
+  ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability());
+  ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent());
+  ASSERT_EQ(injected_authentication_requirements, io_cap_request_reply.GetAuthenticationRequirements());
+  ReceiveIoCapabilityResponse(hci_layer_, device_, hci::IoCapability::NO_INPUT_NO_OUTPUT,
+                              hci::OobDataPresent::NOT_PRESENT, hci::AuthenticationRequirements::NO_BONDING);
+  uint32_t numeric_value = 0x123;
+  ReceiveUserConfirmationRequest(hci_layer_, device_, numeric_value);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto user_conf_request_reply = hci::UserConfirmationRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(user_conf_request_reply.IsValid());
+  ReceiveSimplePairingComplete(hci_layer_, hci::ErrorCode::SUCCESS, device_);
+  std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
+  hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION;
+  ReceiveLinkKeyNotification(hci_layer_, device_, link_key, key_type);
+  ASSERT_EQ(link_key, security_record_->GetLinkKey());
+  ASSERT_EQ(key_type, security_record_->GetKeyType());
+}
+
+// no_input_no_output + display_only is JustWorks no confirmation
+// Needs dialog as per security a bug unless pairing is temporary
+TEST_F(ClassicPairingHandlerTest, locally_initiatied_no_input_no_output_display_only_temp) {
+  hci::IoCapability injected_io_capability = hci::IoCapability::NO_INPUT_NO_OUTPUT;
+  hci::AuthenticationRequirements injected_authentication_requirements = hci::AuthenticationRequirements::NO_BONDING;
+  pairing_handler_->Initiate(true, injected_io_capability, hci::OobDataPresent::NOT_PRESENT,
+                             injected_authentication_requirements);
+  ReceiveLinkKeyRequest(hci_layer_, device_);
+  auto security_command_view = GetLastCommand(hci_layer_);
+  auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view);
+  ASSERT_TRUE(link_key_neg_reply.IsValid());
+  ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode());
+  ReceiveIoCapabilityRequest(hci_layer_, device_);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(io_cap_request_reply.IsValid());
+  ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability());
+  ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent());
+  ASSERT_EQ(injected_authentication_requirements, io_cap_request_reply.GetAuthenticationRequirements());
+  ReceiveIoCapabilityResponse(hci_layer_, device_, hci::IoCapability::DISPLAY_ONLY, hci::OobDataPresent::NOT_PRESENT,
+                              hci::AuthenticationRequirements::NO_BONDING);
+  uint32_t numeric_value = 0x123;
+  ReceiveUserConfirmationRequest(hci_layer_, device_, numeric_value);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto user_conf_request_reply = hci::UserConfirmationRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(user_conf_request_reply.IsValid());
+  ReceiveSimplePairingComplete(hci_layer_, hci::ErrorCode::SUCCESS, device_);
+  std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
+  hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION;
+  ReceiveLinkKeyNotification(hci_layer_, device_, link_key, key_type);
+  ASSERT_EQ(link_key, security_record_->GetLinkKey());
+  ASSERT_EQ(key_type, security_record_->GetKeyType());
+}
+
+// no_input_no_output + display_yes_no is JustWorks no confirmation
+// Needs dialog as per security a bug unless pairing is temporary
+TEST_F(ClassicPairingHandlerTest, locally_initiatied_no_input_no_output_display_yes_no_temp) {
+  hci::IoCapability injected_io_capability = hci::IoCapability::NO_INPUT_NO_OUTPUT;
+  hci::AuthenticationRequirements injected_authentication_requirements = hci::AuthenticationRequirements::NO_BONDING;
+  pairing_handler_->Initiate(true, injected_io_capability, hci::OobDataPresent::NOT_PRESENT,
+                             injected_authentication_requirements);
+  ReceiveLinkKeyRequest(hci_layer_, device_);
+  auto security_command_view = GetLastCommand(hci_layer_);
+  auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view);
+  ASSERT_TRUE(link_key_neg_reply.IsValid());
+  ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode());
+  ReceiveIoCapabilityRequest(hci_layer_, device_);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(io_cap_request_reply.IsValid());
+  ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability());
+  ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent());
+  ASSERT_EQ(injected_authentication_requirements, io_cap_request_reply.GetAuthenticationRequirements());
+  ReceiveIoCapabilityResponse(hci_layer_, device_, hci::IoCapability::DISPLAY_YES_NO, hci::OobDataPresent::NOT_PRESENT,
+                              hci::AuthenticationRequirements::NO_BONDING);
+  uint32_t numeric_value = 0x123;
+  ReceiveUserConfirmationRequest(hci_layer_, device_, numeric_value);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto user_conf_request_reply = hci::UserConfirmationRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(user_conf_request_reply.IsValid());
+  ReceiveSimplePairingComplete(hci_layer_, hci::ErrorCode::SUCCESS, device_);
+  std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
+  hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION;
+  ReceiveLinkKeyNotification(hci_layer_, device_, link_key, key_type);
+  ASSERT_EQ(link_key, security_record_->GetLinkKey());
+  ASSERT_EQ(key_type, security_record_->GetKeyType());
+}
+
+// no_input_no_output + keyboard_only is JustWorks no confirmation
+// Needs dialog as per security a bug unless pairing is temporary
+TEST_F(ClassicPairingHandlerTest, locally_initiatied_no_input_no_output_keyboard_only_temp) {
+  hci::IoCapability injected_io_capability = hci::IoCapability::NO_INPUT_NO_OUTPUT;
+  hci::AuthenticationRequirements injected_authentication_requirements = hci::AuthenticationRequirements::NO_BONDING;
+  pairing_handler_->Initiate(true, injected_io_capability, hci::OobDataPresent::NOT_PRESENT,
+                             injected_authentication_requirements);
+  ReceiveLinkKeyRequest(hci_layer_, device_);
+  auto security_command_view = GetLastCommand(hci_layer_);
+  auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view);
+  ASSERT_TRUE(link_key_neg_reply.IsValid());
+  ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode());
+  ReceiveIoCapabilityRequest(hci_layer_, device_);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(io_cap_request_reply.IsValid());
+  ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability());
+  ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent());
+  ASSERT_EQ(injected_authentication_requirements, io_cap_request_reply.GetAuthenticationRequirements());
+  ReceiveIoCapabilityResponse(hci_layer_, device_, hci::IoCapability::KEYBOARD_ONLY, hci::OobDataPresent::NOT_PRESENT,
+                              hci::AuthenticationRequirements::NO_BONDING);
+  uint32_t numeric_value = 0x123;
+  ReceiveUserConfirmationRequest(hci_layer_, device_, numeric_value);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto user_conf_request_reply = hci::UserConfirmationRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(user_conf_request_reply.IsValid());
+  ReceiveSimplePairingComplete(hci_layer_, hci::ErrorCode::SUCCESS, device_);
+  std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
+  hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION;
+  ReceiveLinkKeyNotification(hci_layer_, device_, link_key, key_type);
+  ASSERT_EQ(link_key, security_record_->GetLinkKey());
+  ASSERT_EQ(key_type, security_record_->GetKeyType());
+}
+
+// no_input_no_output + no_input_no_output is JustWorks no confirmation
+// Needs dialog as per security a bug unless pairing is temporary
+TEST_F(ClassicPairingHandlerTest, locally_initiatied_no_input_no_output_no_input_no_output_temp) {
+  hci::IoCapability injected_io_capability = hci::IoCapability::NO_INPUT_NO_OUTPUT;
+  hci::AuthenticationRequirements injected_authentication_requirements = hci::AuthenticationRequirements::NO_BONDING;
+  pairing_handler_->Initiate(true, injected_io_capability, hci::OobDataPresent::NOT_PRESENT,
+                             injected_authentication_requirements);
+  ReceiveLinkKeyRequest(hci_layer_, device_);
+  auto security_command_view = GetLastCommand(hci_layer_);
+  auto link_key_neg_reply = hci::LinkKeyRequestNegativeReplyView::Create(security_command_view);
+  ASSERT_TRUE(link_key_neg_reply.IsValid());
+  ASSERT_EQ(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, link_key_neg_reply.GetOpCode());
+  ReceiveIoCapabilityRequest(hci_layer_, device_);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::IO_CAPABILITY_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto io_cap_request_reply = hci::IoCapabilityRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(io_cap_request_reply.IsValid());
+  ASSERT_EQ(injected_io_capability, io_cap_request_reply.GetIoCapability());
+  ASSERT_EQ(hci::OobDataPresent::NOT_PRESENT, io_cap_request_reply.GetOobPresent());
+  ASSERT_EQ(injected_authentication_requirements, io_cap_request_reply.GetAuthenticationRequirements());
+  ReceiveIoCapabilityResponse(hci_layer_, device_, hci::IoCapability::NO_INPUT_NO_OUTPUT,
+                              hci::OobDataPresent::NOT_PRESENT, hci::AuthenticationRequirements::NO_BONDING);
+  uint32_t numeric_value = 0x123;
+  ReceiveUserConfirmationRequest(hci_layer_, device_, numeric_value);
+  security_command_view = GetLastCommand(hci_layer_);
+  ASSERT_EQ(OpCode::USER_CONFIRMATION_REQUEST_REPLY, security_command_view.GetOpCode());
+  auto user_conf_request_reply = hci::UserConfirmationRequestReplyView::Create(security_command_view);
+  ASSERT_TRUE(user_conf_request_reply.IsValid());
+  ReceiveSimplePairingComplete(hci_layer_, hci::ErrorCode::SUCCESS, device_);
+  std::array<uint8_t, 16> link_key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
+  hci::KeyType key_type = hci::KeyType::DEBUG_COMBINATION;
+  ReceiveLinkKeyNotification(hci_layer_, device_, link_key, key_type);
+  ASSERT_EQ(link_key, security_record_->GetLinkKey());
+  ASSERT_EQ(key_type, security_record_->GetKeyType());
+}
+
+// Remotely initiated
+
+// Collisions
+
+}  // namespace
+}  // namespace channel
+}  // namespace security
+}  // namespace bluetooth
diff --git a/gd/security/pairing/pairing_handler.h b/gd/security/pairing/pairing_handler.h
index 61cad62..886b1a4 100644
--- a/gd/security/pairing/pairing_handler.h
+++ b/gd/security/pairing/pairing_handler.h
@@ -1,4 +1,4 @@
-/******************************************************************************
+/*
  *
  *  Copyright 2019 The Android Open Source Project
  *
@@ -14,13 +14,13 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- ******************************************************************************/
+ */
 #pragma once
 
-#include <memory>
-#include <vector>
+#include <utility>
 
-#include "hci/device.h"
+#include "hci/address_with_type.h"
+#include "hci/hci_packets.h"
 #include "security/channel/security_manager_channel.h"
 #include "security/record/security_record.h"
 #include "security/smp_packets.h"
@@ -36,14 +36,42 @@
  */
 class PairingHandler {
  public:
-  PairingHandler(std::shared_ptr<record::SecurityRecord> record) : record_(record){};
+  PairingHandler(channel::SecurityManagerChannel* security_manager_channel,
+                 std::shared_ptr<record::SecurityRecord> record)
+      : security_manager_channel_(security_manager_channel), record_(std::move(record)) {}
   virtual ~PairingHandler() = default;
 
+  // Classic
+  virtual void Initiate(bool locally_initiated, hci::IoCapability io_capability, hci::OobDataPresent oob_present,
+                        hci::AuthenticationRequirements auth_requirements) = 0;  // This is for local initiated only
+  virtual void Cancel() = 0;
+  virtual void OnReceive(hci::ChangeConnectionLinkKeyCompleteView packet) = 0;
+  virtual void OnReceive(hci::MasterLinkKeyCompleteView packet) = 0;
+  virtual void OnReceive(hci::PinCodeRequestView packet) = 0;
+  virtual void OnReceive(hci::LinkKeyRequestView packet) = 0;
+  virtual void OnReceive(hci::LinkKeyNotificationView packet) = 0;
+  virtual void OnReceive(hci::IoCapabilityRequestView packet) = 0;
+  virtual void OnReceive(hci::IoCapabilityResponseView packet) = 0;
+  virtual void OnReceive(hci::SimplePairingCompleteView packet) = 0;
+  virtual void OnReceive(hci::ReturnLinkKeysView packet) = 0;
+  virtual void OnReceive(hci::EncryptionChangeView packet) = 0;
+  virtual void OnReceive(hci::EncryptionKeyRefreshCompleteView packet) = 0;
+  virtual void OnReceive(hci::RemoteOobDataRequestView packet) = 0;
+  virtual void OnReceive(hci::UserPasskeyNotificationView packet) = 0;
+  virtual void OnReceive(hci::KeypressNotificationView packet) = 0;
+  virtual void OnReceive(hci::UserConfirmationRequestView packet) = 0;
+  virtual void OnReceive(hci::UserPasskeyRequestView packet) = 0;
+
+ protected:
   std::shared_ptr<record::SecurityRecord> GetRecord() {
     return record_;
   }
+  channel::SecurityManagerChannel* GetChannel() {
+    return security_manager_channel_;
+  }
 
  private:
+  channel::SecurityManagerChannel* security_manager_channel_ __attribute__((unused));
   std::shared_ptr<record::SecurityRecord> record_ __attribute__((unused));
 };
 
diff --git a/gd/security/record/security_record.h b/gd/security/record/security_record.h
index 0c78113..58f047b 100644
--- a/gd/security/record/security_record.h
+++ b/gd/security/record/security_record.h
@@ -1,4 +1,4 @@
-/******************************************************************************
+/*
  *
  *  Copyright 2019 The Android Open Source Project
  *
@@ -14,23 +14,24 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- ******************************************************************************/
+ */
 
 #pragma once
 
 #include <memory>
+#include <utility>
 
-#include "hci/device.h"
+#include "hci/address_with_type.h"
 
 namespace bluetooth {
 namespace security {
 namespace record {
 
-enum BondState { NOT_BONDED, PAIRING, BONDED };
+enum BondState { NOT_BONDED, PAIRING, PAIRED, BONDED };
 
 class SecurityRecord {
  public:
-  SecurityRecord(std::shared_ptr<hci::Device> device) : device_(device), state_(NOT_BONDED) {}
+  explicit SecurityRecord(hci::AddressWithType device) : device_(device), state_(NOT_BONDED) {}
 
   /**
    * Returns true if the device is bonded to another device
@@ -39,6 +40,10 @@
     return state_ == BONDED;
   }
 
+  bool IsPaired() {
+    return state_ == PAIRED;
+  }
+
   /**
    * Returns true if a device is currently pairing to another device
    */
@@ -46,13 +51,28 @@
     return state_ == PAIRING;
   }
 
-  std::shared_ptr<hci::Device> GetDevice() {
+  void SetLinkKey(std::array<uint8_t, 16> link_key, hci::KeyType key_type) {
+    link_key_ = link_key;
+    key_type_ = key_type;
+  }
+
+  std::array<uint8_t, 16> GetLinkKey() {
+    return link_key_;
+  }
+
+  hci::KeyType GetKeyType() {
+    return key_type_;
+  }
+
+  hci::AddressWithType GetDevice() {
     return device_;
   }
 
  private:
-  const std::shared_ptr<hci::Device> device_;
+  const hci::AddressWithType device_;
   BondState state_;
+  std::array<uint8_t, 16> link_key_ = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+  hci::KeyType key_type_ = hci::KeyType::DEBUG_COMBINATION;
 };
 
 }  // namespace record
diff --git a/gd/security/security_manager.cc b/gd/security/security_manager.cc
index 40858a9..f9c1440 100644
--- a/gd/security/security_manager.cc
+++ b/gd/security/security_manager.cc
@@ -1,4 +1,4 @@
-/******************************************************************************
+/*
  *
  *  Copyright 2019 The Android Open Source Project
  *
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- ******************************************************************************/
+ */
 #include "security_manager.h"
 
 #include "os/log.h"
@@ -29,22 +29,22 @@
       common::BindOnce(&internal::SecurityManagerImpl::Init, common::Unretained(security_manager_impl_)));
 }
 
-void SecurityManager::CreateBond(std::shared_ptr<hci::ClassicDevice> device) {
+void SecurityManager::CreateBond(hci::AddressWithType device) {
   security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::CreateBond,
                                            common::Unretained(security_manager_impl_),
-                                           std::forward<std::shared_ptr<hci::ClassicDevice>>(device)));
+                                           std::forward<hci::AddressWithType>(device)));
 }
 
-void SecurityManager::CancelBond(std::shared_ptr<hci::ClassicDevice> device) {
+void SecurityManager::CancelBond(hci::AddressWithType device) {
   security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::CancelBond,
                                            common::Unretained(security_manager_impl_),
-                                           std::forward<std::shared_ptr<hci::ClassicDevice>>(device)));
+                                           std::forward<hci::AddressWithType>(device)));
 }
 
-void SecurityManager::RemoveBond(std::shared_ptr<hci::ClassicDevice> device) {
+void SecurityManager::RemoveBond(hci::AddressWithType device) {
   security_handler_->Post(common::BindOnce(&internal::SecurityManagerImpl::RemoveBond,
                                            common::Unretained(security_manager_impl_),
-                                           std::forward<std::shared_ptr<hci::ClassicDevice>>(device)));
+                                           std::forward<hci::AddressWithType>(device)));
 }
 
 void SecurityManager::RegisterCallbackListener(ISecurityManagerListener* listener, os::Handler* handler) {
diff --git a/gd/security/security_manager.h b/gd/security/security_manager.h
index d83c8d3..2a9f2e3 100644
--- a/gd/security/security_manager.h
+++ b/gd/security/security_manager.h
@@ -1,4 +1,4 @@
-/******************************************************************************
+/*
  *
  *  Copyright 2019 The Android Open Source Project
  *
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- ******************************************************************************/
+ */
 
 #pragma once
 
@@ -22,7 +22,6 @@
 #include <vector>
 
 #include "hci/address_with_type.h"
-#include "hci/device.h"
 #include "security/internal/security_manager_impl.h"
 
 namespace bluetooth {
@@ -75,21 +74,21 @@
    *
    * @param device pointer to device we want to bond with
    */
-  void CreateBond(std::shared_ptr<hci::ClassicDevice> device);
+  void CreateBond(hci::AddressWithType device);
 
   /**
    * Cancels the pairing process for this device.
    *
    * @param device pointer to device with which we want to cancel our bond
    */
-  void CancelBond(std::shared_ptr<bluetooth::hci::ClassicDevice> device);
+  void CancelBond(hci::AddressWithType device);
 
   /**
    * Disassociates the device and removes the persistent LTK
    *
    * @param device pointer to device we want to forget
    */
-  void RemoveBond(std::shared_ptr<bluetooth::hci::ClassicDevice> device);
+  void RemoveBond(hci::AddressWithType device);
 
   /**
    * Register to listen for callback events from SecurityManager
diff --git a/gd/security/security_module.cc b/gd/security/security_module.cc
index 58b1f8c..b1f7c66 100644
--- a/gd/security/security_module.cc
+++ b/gd/security/security_module.cc
@@ -45,6 +45,9 @@
   channel::SecurityManagerChannel* security_manager_channel_;
   internal::SecurityManagerImpl security_manager_impl{security_handler_, l2cap_le_module_, l2cap_classic_module_,
                                                       security_manager_channel_};
+  ~impl() {
+    delete security_manager_channel_;
+  }
 };
 
 void SecurityModule::ListDependencies(ModuleList* list) {
diff --git a/gd/security/test/fake_hci_layer.h b/gd/security/test/fake_hci_layer.h
index 84eff90..6866b34 100644
--- a/gd/security/test/fake_hci_layer.h
+++ b/gd/security/test/fake_hci_layer.h
@@ -1,4 +1,4 @@
-/******************************************************************************
+/*
  *
  *  Copyright 2019 The Android Open Source Project
  *
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- ******************************************************************************/
+ */
 
 #include "common/bind.h"
 #include "hci/hci_layer.h"
@@ -98,7 +98,7 @@
     EventPacketView event = EventPacketView::Create(packet);
     ASSERT_TRUE(event.IsValid());
     EventCode event_code = event.GetEventCode();
-    EXPECT_TRUE(registered_events_.find(event_code) != registered_events_.end());
+    ASSERT_TRUE(registered_events_.find(event_code) != registered_events_.end());
     registered_events_[event_code].Run(event);
   }