// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/components/tether/ble_connection_manager.h"

#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "chromeos/components/multidevice/remote_device_ref.h"
#include "chromeos/components/proximity_auth/logging/logging.h"
#include "chromeos/components/tether/timer_factory.h"
#include "chromeos/services/secure_channel/ble_constants.h"
#include "chromeos/services/secure_channel/ble_weave_client_connection.h"
#include "device/bluetooth/bluetooth_uuid.h"

namespace chromeos {

namespace tether {

namespace {

const char kTetherFeature[] = "magic_tether";

std::string StateChangeDetailToString(
    BleConnectionManager::StateChangeDetail state_change_detail) {
  switch (state_change_detail) {
    case BleConnectionManager::StateChangeDetail::STATE_CHANGE_DETAIL_NONE:
      return "[none]";
    case BleConnectionManager::StateChangeDetail::
        STATE_CHANGE_DETAIL_COULD_NOT_ATTEMPT_CONNECTION:
      return "[could not attempt connection]";
    case BleConnectionManager::StateChangeDetail::
        STATE_CHANGE_DETAIL_GATT_CONNECTION_WAS_ATTEMPTED:
      return "[GATT connection was attempted]";
    case BleConnectionManager::StateChangeDetail::
        STATE_CHANGE_DETAIL_INTERRUPTED_BY_HIGHER_PRIORITY:
      return "[attempt interrupted by higher priority]";
    case BleConnectionManager::StateChangeDetail::
        STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED:
      return "[device was unregistered]";
    default:
      NOTREACHED();
      return std::string();
  }
}

}  // namespace

const int64_t BleConnectionManager::kAdvertisingTimeoutMillis = 12000;
const int64_t BleConnectionManager::kFailImmediatelyTimeoutMillis = 0;

BleConnectionManager::ConnectionMetadata::ConnectionMetadata(
    const std::string& device_id,
    std::unique_ptr<base::OneShotTimer> timer,
    base::WeakPtr<BleConnectionManager> manager)
    : device_id_(device_id),
      connection_attempt_timeout_timer_(std::move(timer)),
      manager_(manager),
      weak_ptr_factory_(this) {}

BleConnectionManager::ConnectionMetadata::~ConnectionMetadata() = default;

void BleConnectionManager::ConnectionMetadata::RegisterConnectionRequest(
    const base::UnguessableToken& request_id,
    secure_channel::ConnectionPriority connection_priority) {
  DCHECK(!base::ContainsKey(request_id_to_priority_map_, request_id));
  request_id_to_priority_map_.insert(
      std::make_pair(request_id, connection_priority));
}

void BleConnectionManager::ConnectionMetadata::UnregisterConnectionRequest(
    const base::UnguessableToken& request_id) {
  request_id_to_priority_map_.erase(request_id);
}

secure_channel::ConnectionPriority
BleConnectionManager::ConnectionMetadata::GetConnectionPriority() {
  DCHECK(HasPendingConnectionRequests());

  secure_channel::ConnectionPriority highest_priority =
      secure_channel::ConnectionPriority::kLow;
  for (const auto& map_entry : request_id_to_priority_map_) {
    if (map_entry.second > highest_priority)
      highest_priority = map_entry.second;
  }

  return highest_priority;
}

bool BleConnectionManager::ConnectionMetadata::HasPendingConnectionRequests()
    const {
  return !request_id_to_priority_map_.empty();
}

bool BleConnectionManager::ConnectionMetadata::HasEstablishedConnection()
    const {
  return secure_channel_.get();
}

secure_channel::SecureChannel::Status
BleConnectionManager::ConnectionMetadata::GetStatus() const {
  if (connection_attempt_timeout_timer_->IsRunning()) {
    // If the timer is running, a connection attempt is in progress but a
    // channel has not been established.
    return secure_channel::SecureChannel::Status::CONNECTING;
  } else if (!HasEstablishedConnection()) {
    // If there is no timer and a channel has not been established, the channel
    // is disconnected.
    return secure_channel::SecureChannel::Status::DISCONNECTED;
  }

  // If a channel has been established, return its status.
  return secure_channel_->status();
}

void BleConnectionManager::ConnectionMetadata::StartConnectionAttemptTimer(
    bool fail_immediately) {
  DCHECK(!secure_channel_);
  DCHECK(!connection_attempt_timeout_timer_->IsRunning());

  int64_t timeout_millis = fail_immediately ? kFailImmediatelyTimeoutMillis
                                            : kAdvertisingTimeoutMillis;

  connection_attempt_timeout_timer_->Start(
      FROM_HERE, base::TimeDelta::FromMilliseconds(timeout_millis),
      base::Bind(&ConnectionMetadata::OnConnectionAttemptTimeout,
                 weak_ptr_factory_.GetWeakPtr()));
}

void BleConnectionManager::ConnectionMetadata::StopConnectionAttemptTimer() {
  DCHECK(!secure_channel_);
  connection_attempt_timeout_timer_->Stop();
}

void BleConnectionManager::ConnectionMetadata::OnConnectionAttemptTimeout() {
  manager_->OnConnectionAttemptTimeout(device_id_);
}

bool BleConnectionManager::ConnectionMetadata::HasSecureChannel() {
  return secure_channel_ != nullptr;
}

void BleConnectionManager::ConnectionMetadata::SetSecureChannel(
    std::unique_ptr<secure_channel::SecureChannel> secure_channel) {
  DCHECK(!secure_channel_);

  // The connection has succeeded, so cancel the timeout.
  connection_attempt_timeout_timer_->Stop();

  secure_channel_ = std::move(secure_channel);
  secure_channel_->AddObserver(this);
  secure_channel_->Initialize();
}

int BleConnectionManager::ConnectionMetadata::SendMessage(
    const std::string& payload) {
  DCHECK(GetStatus() == secure_channel::SecureChannel::Status::AUTHENTICATED);
  return secure_channel_->SendMessage(std::string(kTetherFeature), payload);
}

void BleConnectionManager::ConnectionMetadata::Disconnect() {
  DCHECK(HasSecureChannel());
  secure_channel_->Disconnect();
}

void BleConnectionManager::ConnectionMetadata::OnSecureChannelStatusChanged(
    secure_channel::SecureChannel* secure_channel,
    const secure_channel::SecureChannel::Status& old_status,
    const secure_channel::SecureChannel::Status& new_status) {
  DCHECK(secure_channel_.get() == secure_channel);

  if (new_status == secure_channel::SecureChannel::Status::CONNECTING) {
    // BleConnectionManager already broadcasts "disconnected => connecting"
    // status updates when a connection attempt begins, so there is no need to
    // handle this case.
    return;
  }

  // Make a copy of the two statuses. If |secure_channel_.reset()| is called
  // below, the SecureChannel instance will be destroyed and |old_status| and
  // |new_status| may refer to memory which has been deleted.
  const secure_channel::SecureChannel::Status old_status_copy = old_status;
  const secure_channel::SecureChannel::Status new_status_copy = new_status;

  StateChangeDetail state_change_detail =
      StateChangeDetail::STATE_CHANGE_DETAIL_NONE;

  if (new_status == secure_channel::SecureChannel::Status::DISCONNECTED) {
    secure_channel_->RemoveObserver(this);
    secure_channel_.reset();
    state_change_detail =
        StateChangeDetail::STATE_CHANGE_DETAIL_GATT_CONNECTION_WAS_ATTEMPTED;
  }

  manager_->OnSecureChannelStatusChanged(device_id_, old_status_copy,
                                         new_status_copy, state_change_detail);
}

void BleConnectionManager::ConnectionMetadata::OnMessageReceived(
    secure_channel::SecureChannel* secure_channel,
    const std::string& feature,
    const std::string& payload) {
  DCHECK(secure_channel_.get() == secure_channel);
  if (feature != std::string(kTetherFeature)) {
    // If the message received was not a tether feature, ignore it.
    return;
  }

  manager_->NotifyMessageReceived(device_id_, payload);
}

void BleConnectionManager::ConnectionMetadata::OnMessageSent(
    secure_channel::SecureChannel* secure_channel,
    int sequence_number) {
  DCHECK(secure_channel_.get() == secure_channel);
  PA_LOG(VERBOSE) << "Message sent successfully to device with ID \""
                  << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                         device_id_)
                  << "\"; message sequence number: " << sequence_number;
  manager_->NotifyMessageSent(sequence_number);
}

BleConnectionManager::BleConnectionManager(
    scoped_refptr<device::BluetoothAdapter> adapter,
    BleAdvertisementDeviceQueue* ble_advertisement_device_queue,
    BleAdvertiser* ble_advertiser,
    BleScanner* ble_scanner)
    : adapter_(adapter),
      ble_advertisement_device_queue_(ble_advertisement_device_queue),
      ble_advertiser_(ble_advertiser),
      ble_scanner_(ble_scanner),
      timer_factory_(std::make_unique<TimerFactory>()),
      has_registered_observer_(false),
      weak_ptr_factory_(this) {}

BleConnectionManager::~BleConnectionManager() {
  if (has_registered_observer_) {
    ble_scanner_->RemoveObserver(this);
  }
}

void BleConnectionManager::RegisterRemoteDevice(
    const std::string& device_id,
    const base::UnguessableToken& request_id,
    secure_channel::ConnectionPriority connection_priority) {
  if (!has_registered_observer_) {
    ble_scanner_->AddObserver(this);
  }
  has_registered_observer_ = true;

  PA_LOG(VERBOSE) << "Register - Device ID: \""
                  << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                         device_id)
                  << "\", Request ID: " << request_id
                  << ", Priority: " << connection_priority;

  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
  if (!connection_metadata)
    connection_metadata = AddMetadataForDevice(device_id);

  connection_metadata->RegisterConnectionRequest(request_id,
                                                 connection_priority);
  UpdateConnectionAttempts();
}

void BleConnectionManager::UnregisterRemoteDevice(
    const std::string& device_id,
    const base::UnguessableToken& request_id) {
  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
  if (!connection_metadata) {
    PA_LOG(WARNING) << "Tried to unregister device, but was not registered - "
                    << "Device ID: \""
                    << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                           device_id)
                    << "\", Request ID: " << request_id;
    return;
  }

  PA_LOG(VERBOSE) << "Unregister - Device ID: \""
                  << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                         device_id)
                  << "\", Request ID: " << request_id;

  connection_metadata->UnregisterConnectionRequest(request_id);
  if (!connection_metadata->HasPendingConnectionRequests()) {
    if (connection_metadata->HasEstablishedConnection()) {
      connection_metadata->Disconnect();
    } else {
      // |device_id| references memory that will be deleted below; make a copy.
      const std::string device_id_copy = device_id;
      secure_channel::SecureChannel::Status status_before_erase =
          connection_metadata->GetStatus();
      device_id_to_metadata_map_.erase(device_id_copy);

      if (status_before_erase ==
          secure_channel::SecureChannel::Status::CONNECTING) {
        StopConnectionAttemptAndMoveToEndOfQueue(device_id_copy);
        NotifySecureChannelStatusChanged(
            device_id_copy, secure_channel::SecureChannel::Status::CONNECTING,
            secure_channel::SecureChannel::Status::DISCONNECTED,
            StateChangeDetail::STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED);
      }
    }
  }

  UpdateConnectionAttempts();
}

int BleConnectionManager::SendMessage(const std::string& device_id,
                                      const std::string& message) {
  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
  if (!connection_metadata ||
      connection_metadata->GetStatus() !=
          secure_channel::SecureChannel::Status::AUTHENTICATED) {
    PA_LOG(ERROR) << "SendMessage(): Error - no authenticated channel. "
                  << "Device ID: \""
                  << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                         device_id)
                  << "\", Message: \"" << message << "\"";
    return -1;
  }

  PA_LOG(VERBOSE) << "SendMessage(): Device ID: \""
                  << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                         device_id)
                  << "\", Message: \"" << message << "\"";
  return connection_metadata->SendMessage(message);
}

bool BleConnectionManager::GetStatusForDevice(
    const std::string& device_id,
    secure_channel::SecureChannel::Status* status) const {
  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
  if (!connection_metadata)
    return false;

  *status = connection_metadata->GetStatus();
  return true;
}

void BleConnectionManager::AddObserver(Observer* observer) {
  observer_list_.AddObserver(observer);
}

void BleConnectionManager::RemoveObserver(Observer* observer) {
  observer_list_.RemoveObserver(observer);
}

void BleConnectionManager::AddMetricsObserver(MetricsObserver* observer) {
  metrics_observer_list_.AddObserver(observer);
}

void BleConnectionManager::RemoveMetricsObserver(MetricsObserver* observer) {
  metrics_observer_list_.RemoveObserver(observer);
}

void BleConnectionManager::OnReceivedAdvertisementFromDevice(
    multidevice::RemoteDeviceRef remote_device,
    device::BluetoothDevice* bluetooth_device,
    bool is_background_advertisement) {
  const std::string device_id = remote_device.GetDeviceId();

  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
  if (!connection_metadata) {
    // If an advertisement  is received from a device that is not registered,
    // ignore it.
    PA_LOG(WARNING) << "Received an advertisement from a device which is not "
                    << "registered. Bluetooth address: "
                    << bluetooth_device->GetAddress() << ", Remote Device "
                    << "ID: \"" << remote_device.GetTruncatedDeviceIdForLogs()
                    << "\".";
    return;
  }

  if (connection_metadata->HasSecureChannel()) {
    PA_LOG(WARNING) << "Received another advertisement from a registered "
                    << "device which is already being actively communicated "
                    << "with. Bluetooth address: "
                    << bluetooth_device->GetAddress() << ", Remote Device "
                    << "ID: \"" << remote_device.GetTruncatedDeviceIdForLogs()
                    << "\".";
    return;
  }

  PA_LOG(VERBOSE) << "Received advertisement - Device ID: \""
                  << remote_device.GetTruncatedDeviceIdForLogs()
                  << "\". Starting authentication handshake.";

  device_id_to_is_background_advertisement_map_[device_id] =
      is_background_advertisement;
  NotifyAdvertisementReceived(device_id, is_background_advertisement);

  // Stop trying to connect to that device, since it has been found.
  StopConnectionAttemptAndMoveToEndOfQueue(device_id);

  // Create a connection to that device.
  std::unique_ptr<secure_channel::Connection> connection = secure_channel::
      weave::BluetoothLowEnergyWeaveClientConnection::Factory::NewInstance(
          remote_device, adapter_,
          device::BluetoothUUID(secure_channel::kGattServerUuid),
          bluetooth_device, false /* should_set_low_connection_latency */);
  std::unique_ptr<secure_channel::SecureChannel> secure_channel =
      secure_channel::SecureChannel::Factory::NewInstance(
          std::move(connection));
  connection_metadata->SetSecureChannel(std::move(secure_channel));

  UpdateConnectionAttempts();
}

BleConnectionManager::ConnectionMetadata*
BleConnectionManager::GetConnectionMetadata(
    const std::string& device_id) const {
  const auto map_iter = device_id_to_metadata_map_.find(device_id);
  if (map_iter == device_id_to_metadata_map_.end())
    return nullptr;

  return map_iter->second.get();
}

BleConnectionManager::ConnectionMetadata*
BleConnectionManager::AddMetadataForDevice(const std::string& device_id) {
  ConnectionMetadata* existing_data = GetConnectionMetadata(device_id);
  if (existing_data)
    return existing_data;

  // Create the metadata.
  std::unique_ptr<ConnectionMetadata> metadata = base::WrapUnique(
      new ConnectionMetadata(device_id, timer_factory_->CreateOneShotTimer(),
                             weak_ptr_factory_.GetWeakPtr()));
  ConnectionMetadata* metadata_raw_ptr = metadata.get();

  // Add it to the map.
  device_id_to_metadata_map_.emplace(
      std::pair<std::string, std::unique_ptr<ConnectionMetadata>>(
          device_id, std::move(metadata)));

  return metadata_raw_ptr;
}

void BleConnectionManager::UpdateConnectionAttempts() {
  UpdateAdvertisementQueue();

  std::vector<std::string> should_advertise_to =
      ble_advertisement_device_queue_->GetDeviceIdsToWhichToAdvertise();
  DCHECK(should_advertise_to.size() <=
         secure_channel::kMaxConcurrentAdvertisements);

  // Generate a list of devices which are advertising but are not present in
  // |should_advertise_to|.
  std::vector<std::string> device_ids_to_stop;
  for (const auto& map_entry : device_id_to_metadata_map_) {
    if (map_entry.second->GetStatus() ==
            secure_channel::SecureChannel::Status::CONNECTING &&
        !map_entry.second->HasEstablishedConnection() &&
        !base::ContainsValue(should_advertise_to, map_entry.first)) {
      device_ids_to_stop.push_back(map_entry.first);
    }
  }

  // For each device that should not be advertised to, end the connection
  // attempt. Note that this is done outside of the map iteration above because
  // it is possible that EndSuccessfulAttempt() will cause that map to be
  // modified during iteration.
  for (const auto& device_id_to_stop : device_ids_to_stop) {
    PA_LOG(VERBOSE) << "Connection attempt for device ID \""
                    << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                           device_id_to_stop)
                    << "\" interrupted by higher-priority connection.";
    EndUnsuccessfulAttempt(
        device_id_to_stop,
        StateChangeDetail::STATE_CHANGE_DETAIL_INTERRUPTED_BY_HIGHER_PRIORITY);
  }

  for (const auto& device_id : should_advertise_to) {
    ConnectionMetadata* associated_data = GetConnectionMetadata(device_id);
    if (associated_data->GetStatus() !=
        secure_channel::SecureChannel::Status::CONNECTING) {
      // If there is no active attempt to connect to a device at the front of
      // the queue, start a connection attempt.
      StartConnectionAttempt(device_id);
    }
  }
}

void BleConnectionManager::UpdateAdvertisementQueue() {
  std::vector<BleAdvertisementDeviceQueue::PrioritizedDeviceId> prioritized_ids;
  for (const auto& map_entry : device_id_to_metadata_map_) {
    if (map_entry.second->HasEstablishedConnection()) {
      // If there is already an active connection to the device, there is no
      // need to advertise to the device to bootstrap a connection.
      continue;
    }

    prioritized_ids.emplace_back(map_entry.first,
                                 map_entry.second->GetConnectionPriority());
  }

  ble_advertisement_device_queue_->SetPrioritizedDeviceIds(prioritized_ids);
}

void BleConnectionManager::StartConnectionAttempt(
    const std::string& device_id) {
  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
  DCHECK(connection_metadata);

  PA_LOG(VERBOSE) << "Attempting connection - Device ID: \""
                  << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                         device_id)
                  << "\"";

  bool success = ble_scanner_->RegisterScanFilterForDevice(device_id) &&
                 ble_advertiser_->StartAdvertisingToDevice(device_id);

  // Start a timer; if a connection is unable to be created before the timer
  // fires, a timeout occurs. Note that if this class is unable to start both
  // the scanner and advertiser successfully (i.e., |success| is |false|), a
  // the connection fails immediately insetad of waiting for a timeout, which
  // has the effect of quickly sending out "disconnected => connecting =>
  // disconnecting" status updates. The timer is used here instead of a special
  // case in order to route all connection failures through the same code path.
  connection_metadata->StartConnectionAttemptTimer(
      !success /* fail_immediately */);

  // Send a "disconnected => connecting" update to alert clients that a
  // connection attempt for |device_id| is underway.
  NotifySecureChannelStatusChanged(
      device_id, secure_channel::SecureChannel::Status::DISCONNECTED,
      secure_channel::SecureChannel::Status::CONNECTING,
      StateChangeDetail::STATE_CHANGE_DETAIL_NONE);
}

void BleConnectionManager::EndUnsuccessfulAttempt(
    const std::string& device_id,
    StateChangeDetail state_change_detail) {
  GetConnectionMetadata(device_id)->StopConnectionAttemptTimer();
  StopConnectionAttemptAndMoveToEndOfQueue(device_id);

  // Send a "connecting => disconnected" update to alert clients that a
  // connection attempt for |device_id| has failed.
  NotifySecureChannelStatusChanged(
      device_id, secure_channel::SecureChannel::Status::CONNECTING,
      secure_channel::SecureChannel::Status::DISCONNECTED, state_change_detail);
}

void BleConnectionManager::StopConnectionAttemptAndMoveToEndOfQueue(
    const std::string& device_id) {
  ble_scanner_->UnregisterScanFilterForDevice(device_id);
  ble_advertiser_->StopAdvertisingToDevice(device_id);
  ble_advertisement_device_queue_->MoveDeviceToEnd(device_id);
}

void BleConnectionManager::OnConnectionAttemptTimeout(
    const std::string& device_id) {
  PA_LOG(VERBOSE) << "Connection attempt timeout - Device ID \""
                  << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                         device_id)
                  << "\".";
  EndUnsuccessfulAttempt(
      device_id,
      StateChangeDetail::STATE_CHANGE_DETAIL_COULD_NOT_ATTEMPT_CONNECTION);
  UpdateConnectionAttempts();
}

void BleConnectionManager::OnSecureChannelStatusChanged(
    const std::string& device_id,
    const secure_channel::SecureChannel::Status& old_status,
    const secure_channel::SecureChannel::Status& new_status,
    StateChangeDetail state_change_detail) {
  ConnectionMetadata* connection_metadata = GetConnectionMetadata(device_id);
  DCHECK(connection_metadata);

  // Create copies of the references passed to this function. If the map entry
  // is erased below, the references will point to deleted memory.
  const std::string device_id_copy = device_id;
  const secure_channel::SecureChannel::Status old_status_copy = old_status;
  const secure_channel::SecureChannel::Status new_status_copy = new_status;

  if (!connection_metadata->HasPendingConnectionRequests() &&
      new_status == secure_channel::SecureChannel::Status::DISCONNECTED) {
    device_id_to_metadata_map_.erase(device_id_copy);
    state_change_detail =
        StateChangeDetail::STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED;
  }

  NotifySecureChannelStatusChanged(device_id_copy, old_status_copy,
                                   new_status_copy, state_change_detail);
  UpdateConnectionAttempts();
}

void BleConnectionManager::NotifyAdvertisementReceived(
    const std::string& device_id,
    bool is_background_advertisement) {
  for (auto& observer : metrics_observer_list_)
    observer.OnAdvertisementReceived(device_id, is_background_advertisement);
}

void BleConnectionManager::NotifyMessageReceived(std::string device_id,
                                                 std::string payload) {
  PA_LOG(VERBOSE) << "Message received - Device ID: \""
                  << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                         device_id)
                  << "\", Message: \"" << payload << "\".";
  for (auto& observer : observer_list_)
    observer.OnMessageReceived(device_id, payload);
}

void BleConnectionManager::NotifySecureChannelStatusChanged(
    std::string device_id,
    secure_channel::SecureChannel::Status old_status,
    secure_channel::SecureChannel::Status new_status,
    StateChangeDetail state_change_detail) {
  PA_LOG(VERBOSE) << "Status change - Device ID: \""
                  << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                         device_id)
                  << "\": "
                  << secure_channel::SecureChannel::StatusToString(old_status)
                  << " => "
                  << secure_channel::SecureChannel::StatusToString(new_status)
                  << ", State change detail: "
                  << StateChangeDetailToString(state_change_detail);

  for (auto& observer : metrics_observer_list_) {
    if (old_status == secure_channel::SecureChannel::Status::DISCONNECTED &&
        new_status == secure_channel::SecureChannel::Status::CONNECTING) {
      observer.OnConnectionAttemptStarted(device_id);
    } else if (new_status == secure_channel::SecureChannel::Status::CONNECTED) {
      observer.OnConnection(
          device_id, device_id_to_is_background_advertisement_map_[device_id]);
    } else if (new_status ==
               secure_channel::SecureChannel::Status::AUTHENTICATED) {
      observer.OnSecureChannelCreated(
          device_id, device_id_to_is_background_advertisement_map_[device_id]);
    } else if (new_status ==
               secure_channel::SecureChannel::Status::DISCONNECTED) {
      observer.OnDeviceDisconnected(
          device_id, state_change_detail,
          device_id_to_is_background_advertisement_map_[device_id]);
    }
  }

  for (auto& observer : observer_list_) {
    observer.OnSecureChannelStatusChanged(device_id, old_status, new_status,
                                          state_change_detail);
  }
}

void BleConnectionManager::NotifyMessageSent(int sequence_number) {
  for (auto& observer : observer_list_)
    observer.OnMessageSent(sequence_number);
}

void BleConnectionManager::SetTestTimerFactoryForTesting(
    std::unique_ptr<TimerFactory> test_timer_factory) {
  timer_factory_ = std::move(test_timer_factory);
}

}  // namespace tether

}  // namespace chromeos
